1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-07-13 10:06:23 +02:00
Files
php-web-maker/src/utils.js

184 lines
4.4 KiB
JavaScript

(function() {
window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
window.$ = document.querySelector.bind(document);
window.$all = selector => [...document.querySelectorAll(selector)];
var alphaNum =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
/**
* The following 2 functions are supposed to find the next/previous sibling until the
* passed `selector` is matched. But for now it actually finds the next/previous
* element of `this` element in the list of `selector` matched element inside `this`'s
* parent.
* @param Selector that should match for next siblings
* @return element Next element that mathes `selector`
*/
Node.prototype.nextUntil = function(selector) {
const siblings = [...this.parentNode.querySelectorAll(selector)];
const index = siblings.indexOf(this);
return siblings[index + 1];
};
/*
* @param Selector that should match for next siblings
* @return element Next element that mathes `selector`
*/
Node.prototype.previousUntil = function(selector) {
const siblings = [...this.parentNode.querySelectorAll(selector)];
const index = siblings.indexOf(this);
return siblings[index - 1];
};
// https://github.com/substack/semver-compare/blob/master/index.js
function semverCompare(a, b) {
var pa = a.split('.');
var pb = b.split('.');
for (var i = 0; i < 3; i++) {
var na = Number(pa[i]);
var nb = Number(pb[i]);
if (na > nb) {
return 1;
}
if (nb > na) {
return -1;
}
if (!isNaN(na) && isNaN(nb)) {
return 1;
}
if (isNaN(na) && !isNaN(nb)) {
return -1;
}
}
return 0;
}
function generateRandomId(len) {
var length = len || 10;
var id = '';
for (var i = length; i--; ) {
id += alphaNum[~~(Math.random() * alphaNum.length)];
}
return id;
}
function onButtonClick(btn, listener) {
btn.addEventListener('click', function buttonClickListener(e) {
listener(e);
return false;
});
}
function log() {
if (window.DEBUG) {
console.log(...arguments);
}
}
/**
* Adds timed limit on the loops found in the passed code.
* Contributed by Ariya Hidayat!
* @param code {string} Code to be protected from infinite loops.
*/
function addInfiniteLoopProtection(code) {
var loopId = 1;
var patches = [];
var varPrefix = '_wmloopvar';
var varStr = 'var %d = Date.now();\n';
var checkStr =
'\nif (Date.now() - %d > 1000) { window.top.previewException(new Error("Infinite loop")); break;}\n';
esprima.parse(code, { tolerant: true, range: true, jsx: true }, function(
node
) {
switch (node.type) {
case 'DoWhileStatement':
case 'ForStatement':
case 'ForInStatement':
case 'ForOfStatement':
case 'WhileStatement':
var start = 1 + node.body.range[0];
var end = node.body.range[1];
var prolog = checkStr.replace('%d', varPrefix + loopId);
var epilog = '';
if (node.body.type !== 'BlockStatement') {
// `while(1) doThat()` becomes `while(1) {doThat()}`
prolog = '{' + prolog;
epilog = '}';
--start;
}
patches.push({ pos: start, str: prolog });
patches.push({ pos: end, str: epilog });
patches.push({
pos: node.range[0],
str: varStr.replace('%d', varPrefix + loopId)
});
++loopId;
break;
default:
break;
}
});
/* eslint-disable no-param-reassign */
patches
.sort(function(a, b) {
return b.pos - a.pos;
})
.forEach(function(patch) {
code = code.slice(0, patch.pos) + patch.str + code.slice(patch.pos);
});
/* eslint-disable no-param-reassign */
return code;
}
function getHumanDate(timestamp) {
var d = new Date(timestamp);
var retVal =
d.getDate() +
' ' +
[
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
][d.getMonth()] +
' ' +
d.getFullYear();
return retVal;
}
// create a one-time event
function once(node, type, callback) {
// create event
node.addEventListener(type, function(e) {
// remove event
e.target.removeEventListener(type, arguments.callee);
// call handler
return callback(e);
});
}
window.utils = {
semverCompare: semverCompare,
generateRandomId: generateRandomId,
onButtonClick: onButtonClick,
addInfiniteLoopProtection: addInfiniteLoopProtection,
getHumanDate: getHumanDate,
log: log,
once: once
};
})();