Bundle webshitter lib

FossilOrigin-Name: ce5d7f4522f9b7a75ed918b58ba51473975f37d7c9e11a273f5648c481dc14d9
This commit is contained in:
nekobit 2022-10-14 01:51:43 +00:00
parent c2b64cdf33
commit cb0b676cd7
6 changed files with 776 additions and 12 deletions

View File

@ -10,7 +10,9 @@ The goal is to create a frontend that's lightweight enough to be viewed without
usable enough to improve the experience with JS.
Treebird uses C with FCGI, mastodont-c (library designed for Treebird, but can be used
for other applications as well), and plain JavaScript for the frontend (100% optional).
for other applications as well), and **optional** JavaScript for the frontend (100% functional without
javascript, it only helps). Uses [RE:DOM](https://redom.js.org/) (3kb js library) to assist with DOM
creation and native JS apis. (bundled, no need to build)
## Why?

755
dist/js/redom.js vendored Normal file
View File

@ -0,0 +1,755 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.redom = {}));
})(this, (function (exports) { 'use strict';
function createElement (query, ns) {
var ref = parse(query);
var tag = ref.tag;
var id = ref.id;
var className = ref.className;
var element = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
if (id) {
element.id = id;
}
if (className) {
if (ns) {
element.setAttribute('class', className);
} else {
element.className = className;
}
}
return element;
}
function parse (query) {
var chunks = query.split(/([.#])/);
var className = '';
var id = '';
for (var i = 1; i < chunks.length; i += 2) {
switch (chunks[i]) {
case '.':
className += " " + (chunks[i + 1]);
break;
case '#':
id = chunks[i + 1];
}
}
return {
className: className.trim(),
tag: chunks[0] || 'div',
id: id
};
}
function unmount (parent, child) {
var parentEl = getEl(parent);
var childEl = getEl(child);
if (child === childEl && childEl.__redom_view) {
// try to look up the view if not provided
child = childEl.__redom_view;
}
if (childEl.parentNode) {
doUnmount(child, childEl, parentEl);
parentEl.removeChild(childEl);
}
return child;
}
function doUnmount (child, childEl, parentEl) {
var hooks = childEl.__redom_lifecycle;
if (hooksAreEmpty(hooks)) {
childEl.__redom_lifecycle = {};
return;
}
var traverse = parentEl;
if (childEl.__redom_mounted) {
trigger(childEl, 'onunmount');
}
while (traverse) {
var parentHooks = traverse.__redom_lifecycle || {};
for (var hook in hooks) {
if (parentHooks[hook]) {
parentHooks[hook] -= hooks[hook];
}
}
if (hooksAreEmpty(parentHooks)) {
traverse.__redom_lifecycle = null;
}
traverse = traverse.parentNode;
}
}
function hooksAreEmpty (hooks) {
if (hooks == null) {
return true;
}
for (var key in hooks) {
if (hooks[key]) {
return false;
}
}
return true;
}
/* global Node, ShadowRoot */
var hookNames = ['onmount', 'onremount', 'onunmount'];
var shadowRootAvailable = typeof window !== 'undefined' && 'ShadowRoot' in window;
function mount (parent, child, before, replace) {
var parentEl = getEl(parent);
var childEl = getEl(child);
if (child === childEl && childEl.__redom_view) {
// try to look up the view if not provided
child = childEl.__redom_view;
}
if (child !== childEl) {
childEl.__redom_view = child;
}
var wasMounted = childEl.__redom_mounted;
var oldParent = childEl.parentNode;
if (wasMounted && (oldParent !== parentEl)) {
doUnmount(child, childEl, oldParent);
}
if (before != null) {
if (replace) {
var beforeEl = getEl(before);
if (beforeEl.__redom_mounted) {
trigger(beforeEl, 'onunmount');
}
parentEl.replaceChild(childEl, beforeEl);
} else {
parentEl.insertBefore(childEl, getEl(before));
}
} else {
parentEl.appendChild(childEl);
}
doMount(child, childEl, parentEl, oldParent);
return child;
}
function trigger (el, eventName) {
if (eventName === 'onmount' || eventName === 'onremount') {
el.__redom_mounted = true;
} else if (eventName === 'onunmount') {
el.__redom_mounted = false;
}
var hooks = el.__redom_lifecycle;
if (!hooks) {
return;
}
var view = el.__redom_view;
var hookCount = 0;
view && view[eventName] && view[eventName]();
for (var hook in hooks) {
if (hook) {
hookCount++;
}
}
if (hookCount) {
var traverse = el.firstChild;
while (traverse) {
var next = traverse.nextSibling;
trigger(traverse, eventName);
traverse = next;
}
}
}
function doMount (child, childEl, parentEl, oldParent) {
var hooks = childEl.__redom_lifecycle || (childEl.__redom_lifecycle = {});
var remount = (parentEl === oldParent);
var hooksFound = false;
for (var i = 0, list = hookNames; i < list.length; i += 1) {
var hookName = list[i];
if (!remount) { // if already mounted, skip this phase
if (child !== childEl) { // only Views can have lifecycle events
if (hookName in child) {
hooks[hookName] = (hooks[hookName] || 0) + 1;
}
}
}
if (hooks[hookName]) {
hooksFound = true;
}
}
if (!hooksFound) {
childEl.__redom_lifecycle = {};
return;
}
var traverse = parentEl;
var triggered = false;
if (remount || (traverse && traverse.__redom_mounted)) {
trigger(childEl, remount ? 'onremount' : 'onmount');
triggered = true;
}
while (traverse) {
var parent = traverse.parentNode;
var parentHooks = traverse.__redom_lifecycle || (traverse.__redom_lifecycle = {});
for (var hook in hooks) {
parentHooks[hook] = (parentHooks[hook] || 0) + hooks[hook];
}
if (triggered) {
break;
} else {
if (traverse.nodeType === Node.DOCUMENT_NODE ||
(shadowRootAvailable && (traverse instanceof ShadowRoot)) ||
(parent && parent.__redom_mounted)
) {
trigger(traverse, remount ? 'onremount' : 'onmount');
triggered = true;
}
traverse = parent;
}
}
}
function setStyle (view, arg1, arg2) {
var el = getEl(view);
if (typeof arg1 === 'object') {
for (var key in arg1) {
setStyleValue(el, key, arg1[key]);
}
} else {
setStyleValue(el, arg1, arg2);
}
}
function setStyleValue (el, key, value) {
el.style[key] = value == null ? '' : value;
}
/* global SVGElement */
var xlinkns = 'http://www.w3.org/1999/xlink';
function setAttr (view, arg1, arg2) {
setAttrInternal(view, arg1, arg2);
}
function setAttrInternal (view, arg1, arg2, initial) {
var el = getEl(view);
var isObj = typeof arg1 === 'object';
if (isObj) {
for (var key in arg1) {
setAttrInternal(el, key, arg1[key], initial);
}
} else {
var isSVG = el instanceof SVGElement;
var isFunc = typeof arg2 === 'function';
if (arg1 === 'style' && typeof arg2 === 'object') {
setStyle(el, arg2);
} else if (isSVG && isFunc) {
el[arg1] = arg2;
} else if (arg1 === 'dataset') {
setData(el, arg2);
} else if (!isSVG && (arg1 in el || isFunc) && (arg1 !== 'list')) {
el[arg1] = arg2;
} else {
if (isSVG && (arg1 === 'xlink')) {
setXlink(el, arg2);
return;
}
if (initial && arg1 === 'class') {
arg2 = el.className + ' ' + arg2;
}
if (arg2 == null) {
el.removeAttribute(arg1);
} else {
el.setAttribute(arg1, arg2);
}
}
}
}
function setXlink (el, arg1, arg2) {
if (typeof arg1 === 'object') {
for (var key in arg1) {
setXlink(el, key, arg1[key]);
}
} else {
if (arg2 != null) {
el.setAttributeNS(xlinkns, arg1, arg2);
} else {
el.removeAttributeNS(xlinkns, arg1, arg2);
}
}
}
function setData (el, arg1, arg2) {
if (typeof arg1 === 'object') {
for (var key in arg1) {
setData(el, key, arg1[key]);
}
} else {
if (arg2 != null) {
el.dataset[arg1] = arg2;
} else {
delete el.dataset[arg1];
}
}
}
function text (str) {
return document.createTextNode((str != null) ? str : '');
}
function parseArgumentsInternal (element, args, initial) {
for (var i = 0, list = args; i < list.length; i += 1) {
var arg = list[i];
if (arg !== 0 && !arg) {
continue;
}
var type = typeof arg;
if (type === 'function') {
arg(element);
} else if (type === 'string' || type === 'number') {
element.appendChild(text(arg));
} else if (isNode(getEl(arg))) {
mount(element, arg);
} else if (arg.length) {
parseArgumentsInternal(element, arg, initial);
} else if (type === 'object') {
setAttrInternal(element, arg, null, initial);
}
}
}
function ensureEl (parent) {
return typeof parent === 'string' ? html(parent) : getEl(parent);
}
function getEl (parent) {
return (parent.nodeType && parent) || (!parent.el && parent) || getEl(parent.el);
}
function isNode (arg) {
return arg && arg.nodeType;
}
function html (query) {
var args = [], len = arguments.length - 1;
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
var element;
var type = typeof query;
if (type === 'string') {
element = createElement(query);
} else if (type === 'function') {
var Query = query;
element = new (Function.prototype.bind.apply( Query, [ null ].concat( args) ));
} else {
throw new Error('At least one argument required');
}
parseArgumentsInternal(getEl(element), args, true);
return element;
}
var el = html;
var h = html;
html.extend = function extendHtml () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return html.bind.apply(html, [ this ].concat( args ));
};
function setChildren (parent) {
var children = [], len = arguments.length - 1;
while ( len-- > 0 ) children[ len ] = arguments[ len + 1 ];
var parentEl = getEl(parent);
var current = traverse(parent, children, parentEl.firstChild);
while (current) {
var next = current.nextSibling;
unmount(parent, current);
current = next;
}
}
function traverse (parent, children, _current) {
var current = _current;
var childEls = Array(children.length);
for (var i = 0; i < children.length; i++) {
childEls[i] = children[i] && getEl(children[i]);
}
for (var i$1 = 0; i$1 < children.length; i$1++) {
var child = children[i$1];
if (!child) {
continue;
}
var childEl = childEls[i$1];
if (childEl === current) {
current = current.nextSibling;
continue;
}
if (isNode(childEl)) {
var next = current && current.nextSibling;
var exists = child.__redom_index != null;
var replace = exists && next === childEls[i$1 + 1];
mount(parent, child, current, replace);
if (replace) {
current = next;
}
continue;
}
if (child.length != null) {
current = traverse(parent, child, current);
}
}
return current;
}
function listPool (View, key, initData) {
return new ListPool(View, key, initData);
}
var ListPool = function ListPool (View, key, initData) {
this.View = View;
this.initData = initData;
this.oldLookup = {};
this.lookup = {};
this.oldViews = [];
this.views = [];
if (key != null) {
this.key = typeof key === 'function' ? key : propKey(key);
}
};
ListPool.prototype.update = function update (data, context) {
var ref = this;
var View = ref.View;
var key = ref.key;
var initData = ref.initData;
var keySet = key != null;
var oldLookup = this.lookup;
var newLookup = {};
var newViews = Array(data.length);
var oldViews = this.views;
for (var i = 0; i < data.length; i++) {
var item = data[i];
var view = (void 0);
if (keySet) {
var id = key(item);
view = oldLookup[id] || new View(initData, item, i, data);
newLookup[id] = view;
view.__redom_id = id;
} else {
view = oldViews[i] || new View(initData, item, i, data);
}
view.update && view.update(item, i, data, context);
var el = getEl(view.el);
el.__redom_view = view;
newViews[i] = view;
}
this.oldViews = oldViews;
this.views = newViews;
this.oldLookup = oldLookup;
this.lookup = newLookup;
};
function propKey (key) {
return function (item) {
return item[key];
};
}
function list (parent, View, key, initData) {
return new List(parent, View, key, initData);
}
var List = function List (parent, View, key, initData) {
this.View = View;
this.initData = initData;
this.views = [];
this.pool = new ListPool(View, key, initData);
this.el = ensureEl(parent);
this.keySet = key != null;
};
List.prototype.update = function update (data, context) {
if ( data === void 0 ) data = [];
var ref = this;
var keySet = ref.keySet;
var oldViews = this.views;
this.pool.update(data, context);
var ref$1 = this.pool;
var views = ref$1.views;
var lookup = ref$1.lookup;
if (keySet) {
for (var i = 0; i < oldViews.length; i++) {
var oldView = oldViews[i];
var id = oldView.__redom_id;
if (lookup[id] == null) {
oldView.__redom_index = null;
unmount(this, oldView);
}
}
}
for (var i$1 = 0; i$1 < views.length; i$1++) {
var view = views[i$1];
view.__redom_index = i$1;
}
setChildren(this, views);
if (keySet) {
this.lookup = lookup;
}
this.views = views;
};
List.extend = function extendList (parent, View, key, initData) {
return List.bind(List, parent, View, key, initData);
};
list.extend = List.extend;
/* global Node */
function place (View, initData) {
return new Place(View, initData);
}
var Place = function Place (View, initData) {
this.el = text('');
this.visible = false;
this.view = null;
this._placeholder = this.el;
if (View instanceof Node) {
this._el = View;
} else if (View.el instanceof Node) {
this._el = View;
this.view = View;
} else {
this._View = View;
}
this._initData = initData;
};
Place.prototype.update = function update (visible, data) {
var placeholder = this._placeholder;
var parentNode = this.el.parentNode;
if (visible) {
if (!this.visible) {
if (this._el) {
mount(parentNode, this._el, placeholder);
unmount(parentNode, placeholder);
this.el = getEl(this._el);
this.visible = visible;
} else {
var View = this._View;
var view = new View(this._initData);
this.el = getEl(view);
this.view = view;
mount(parentNode, view, placeholder);
unmount(parentNode, placeholder);
}
}
this.view && this.view.update && this.view.update(data);
} else {
if (this.visible) {
if (this._el) {
mount(parentNode, placeholder, this._el);
unmount(parentNode, this._el);
this.el = placeholder;
this.visible = visible;
return;
}
mount(parentNode, placeholder, this.view);
unmount(parentNode, this.view);
this.el = placeholder;
this.view = null;
}
}
this.visible = visible;
};
/* global Node */
function router (parent, Views, initData) {
return new Router(parent, Views, initData);
}
var Router = function Router (parent, Views, initData) {
this.el = ensureEl(parent);
this.Views = Views;
this.initData = initData;
};
Router.prototype.update = function update (route, data) {
if (route !== this.route) {
var Views = this.Views;
var View = Views[route];
this.route = route;
if (View && (View instanceof Node || View.el instanceof Node)) {
this.view = View;
} else {
this.view = View && new View(this.initData, data);
}
setChildren(this.el, [this.view]);
}
this.view && this.view.update && this.view.update(data, route);
};
var ns = 'http://www.w3.org/2000/svg';
function svg (query) {
var args = [], len = arguments.length - 1;
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
var element;
var type = typeof query;
if (type === 'string') {
element = createElement(query, ns);
} else if (type === 'function') {
var Query = query;
element = new (Function.prototype.bind.apply( Query, [ null ].concat( args) ));
} else {
throw new Error('At least one argument required');
}
parseArgumentsInternal(getEl(element), args, true);
return element;
}
var s = svg;
svg.extend = function extendSvg () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return svg.bind.apply(svg, [ this ].concat( args ));
};
svg.ns = ns;
exports.List = List;
exports.ListPool = ListPool;
exports.Place = Place;
exports.Router = Router;
exports.el = el;
exports.h = h;
exports.html = html;
exports.list = list;
exports.listPool = listPool;
exports.mount = mount;
exports.place = place;
exports.router = router;
exports.s = s;
exports.setAttr = setAttr;
exports.setChildren = setChildren;
exports.setData = setData;
exports.setStyle = setStyle;
exports.setXlink = setXlink;
exports.svg = svg;
exports.text = text;
exports.unmount = unmount;
Object.defineProperty(exports, '__esModule', { value: true });
}));

1
dist/js/redom.min.js vendored Normal file

File diff suppressed because one or more lines are too long

9
dist/treebird.css vendored
View File

@ -14,12 +14,12 @@
}
*
input
{
transition: .1s box-shadow;
}
*:focus
input:focus
{
outline: 1px solid #aa0000;
box-shadow: 0px 0px 6px #aa00006f;
@ -309,7 +309,10 @@ table.ui-table td
padding-bottom: unset;
height: 26px;
border-right: unset;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
padding-left: 27px;
box-shadow: unset;
transition: width .1s ease;
width: 180px;
}
@ -389,6 +392,8 @@ input[type=email],
input[type=password]
{
padding: 2px;
border-radius: 3px;
box-shadow: 0px 2px 3px #00000005;
border: 1px solid #d3d3d3;
}

View File

@ -16,11 +16,19 @@ use config;
use embed;
use meta;
use login;
# use Devel::Leak;
# my $handle;
# Devel::Leak::NoteSV($handle);
# sub leaky_friend
# {
# $count = Devel::Leak::CheckSV($handle);
# my $leakstr = "Memory: $count SVs\n";
# print STDERR $leakstr;
# }
sub base_page
{
my ($ssn,
@ -49,10 +57,3 @@ sub base_page
return $ret;
}
# sub leaky_friend
# {
# $count = Devel::Leak::CheckSV($handle);
# my $leakstr = "Memory: $count SVs\n";
# print STDERR $leakstr;
# }

View File

@ -25,9 +25,9 @@
<form action="/login/oauth" method="post">
<div class="form-group">
<label for="instance-url">{{%s:instance_url}}: </label>
<label for="instance-url">[% lang('INSTANCE_URL') %]: </label>
<input type="url" id="instance-url" name="instance">
<input class="btn btn-single" type="submit" value="{{%s:instance_submit}}">
<input class="btn btn-single" type="submit" value="[% lang('INSTANCE_SUBMIT') %]">
</div>
</form>
</div>