Compare commits
No commits in common. "111ba98380c8df3a3b7a3069c3bf1fbbdb7e3aa6" and "4aa2b4cb1af129164ba91d61a663550487b1a4c3" have entirely different histories.
111ba98380
...
4aa2b4cb1a
7 changed files with 358 additions and 329 deletions
2
build.js
2
build.js
|
@ -13,7 +13,7 @@ const exec = require('util').promisify(require('child_process').exec);
|
|||
public: pathJoin(__dirname, 'public'),
|
||||
debug: isDebug,
|
||||
swc: {
|
||||
es: 'es5',
|
||||
es: 'es2020',
|
||||
},
|
||||
vars: {
|
||||
html: {
|
||||
|
|
498
package-lock.json
generated
498
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -22,21 +22,6 @@ var FutamiCommon = function(vars) {
|
|||
xhr.setRequestHeader('Cache-Control', 'no-cache');
|
||||
xhr.send();
|
||||
},
|
||||
getApiJson: function(path, onload, onerror, noCache) {
|
||||
if(typeof onload !== 'function')
|
||||
throw 'onload must be specified';
|
||||
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.onload = function() {
|
||||
onload(JSON.parse(xhr.responseText));
|
||||
};
|
||||
if(typeof onerror === 'function')
|
||||
xhr.onerror = function() { onerror(); };
|
||||
xhr.open('GET', get('api') + path);
|
||||
if(noCache)
|
||||
xhr.setRequestHeader('Cache-Control', 'no-cache');
|
||||
xhr.send();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -188,9 +188,9 @@ var AmiContext = function(title, auth, loading) {
|
|||
return;
|
||||
}
|
||||
|
||||
futami.getApiJson('/v1/emotes', function(emotes) {
|
||||
futami.getJson('emotes', function(emotes) {
|
||||
if(Array.isArray(emotes))
|
||||
emoticons.load(emotes);
|
||||
emoticons.loadLegacy(emotes);
|
||||
chat.emoticonList.render(emoticons);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -49,31 +49,44 @@ var AmiEmoticons = function() {
|
|||
};
|
||||
|
||||
var add = function(emote) {
|
||||
if(emote.url.substring(0, 6) === 'https:')
|
||||
emote.url = emote.url.substring(6);
|
||||
|
||||
emotes.push(emote);
|
||||
};
|
||||
|
||||
var addLegacy = function(emoteOld) {
|
||||
var emote = {
|
||||
url: emoteOld.Image.replace('https:', ''),
|
||||
minRank: emoteOld.Hierarchy,
|
||||
strings: [],
|
||||
};
|
||||
for(var i = 0; i < emoteOld.Text.length; ++i)
|
||||
emote.strings.push(emoteOld.Text[i].slice(1, -1));
|
||||
add(emote);
|
||||
};
|
||||
|
||||
return {
|
||||
clear: clear,
|
||||
add: add,
|
||||
addLegacy: addLegacy,
|
||||
load: function(batch) {
|
||||
for(var i in batch)
|
||||
add(batch[i]);
|
||||
},
|
||||
loadLegacy: function(batch) {
|
||||
for(var i in batch)
|
||||
addLegacy(batch[i]);
|
||||
},
|
||||
forEach: function(minRank, callback) {
|
||||
if(minRank === undefined) minRank = 0;
|
||||
for(var i in emotes) {
|
||||
var emote = emotes[i];
|
||||
if(!emote.min_rank || emote.min_rank <= minRank)
|
||||
if(emote.minRank <= minRank)
|
||||
callback(emote);
|
||||
}
|
||||
},
|
||||
any: function(minRank) {
|
||||
if(minRank === undefined) minRank = 0;
|
||||
for(var i in emotes)
|
||||
if(!emotes[i].min_rank || emotes[i].min_rank <= minRank)
|
||||
if(emotes[i].minRank <= minRank)
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
|
@ -81,7 +94,7 @@ var AmiEmoticons = function() {
|
|||
var found = [];
|
||||
for(var i in emotes) {
|
||||
var emote = emotes[i];
|
||||
if(!emote.min_rank || emote.min_rank <= minRank) {
|
||||
if(emote.minRank <= minRank) {
|
||||
for(var j in emote.strings) {
|
||||
var string = emote.strings[j];
|
||||
if(string.indexOf(name) === 0) {
|
||||
|
|
108
src/assproc.js
Normal file
108
src/assproc.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const readline = require('readline');
|
||||
const utils = require('./utils.js');
|
||||
|
||||
exports.process = async function(root, options) {
|
||||
const macroPrefix = options.prefix || '#';
|
||||
const entryPoint = options.entry || '';
|
||||
|
||||
root = fs.realpathSync(root);
|
||||
|
||||
const included = [];
|
||||
|
||||
const processFile = async function(fileName) {
|
||||
const fullPath = path.join(root, fileName);
|
||||
if(included.includes(fullPath))
|
||||
return '';
|
||||
included.push(fullPath);
|
||||
|
||||
if(!fullPath.startsWith(root))
|
||||
return '/* *** INVALID PATH: ' + fullPath + ' */';
|
||||
if(!fs.existsSync(fullPath))
|
||||
return '/* *** FILE NOT FOUND: ' + fullPath + ' */';
|
||||
|
||||
const lines = readline.createInterface({
|
||||
input: fs.createReadStream(fullPath),
|
||||
crlfDelay: Infinity,
|
||||
});
|
||||
|
||||
let output = '';
|
||||
let lastWasEmpty = false;
|
||||
|
||||
if(options.showPath)
|
||||
output += "/* *** PATH: " + fullPath + " */\n";
|
||||
|
||||
for await(const line of lines) {
|
||||
const lineTrimmed = utils.trim(line);
|
||||
if(lineTrimmed === '')
|
||||
continue;
|
||||
|
||||
if(line.startsWith(macroPrefix)) {
|
||||
const args = lineTrimmed.split(' ');
|
||||
const macro = utils.trim(utils.trimStart(args.shift(), macroPrefix));
|
||||
|
||||
switch(macro) {
|
||||
case 'comment':
|
||||
break;
|
||||
|
||||
case 'include': {
|
||||
const includePath = utils.trimEnd(args.join(' '), ';');
|
||||
output += utils.trim(await processFile(includePath));
|
||||
output += "\n";
|
||||
break;
|
||||
}
|
||||
|
||||
case 'buildvars':
|
||||
if(typeof options.buildVars === 'object') {
|
||||
const bvTarget = options.buildVarsTarget || 'window';
|
||||
const bvProps = [];
|
||||
|
||||
for(const bvName in options.buildVars)
|
||||
bvProps.push(`${bvName}: { value: ${JSON.stringify(options.buildVars[bvName])} }`);
|
||||
|
||||
if(Object.keys(bvProps).length > 0)
|
||||
output += `Object.defineProperties(${bvTarget}, { ${bvProps.join(', ')} });\n`;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
output += line;
|
||||
output += "\n";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
output += line;
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
return await processFile(entryPoint);
|
||||
};
|
||||
|
||||
exports.housekeep = function(assetsPath) {
|
||||
const files = fs.readdirSync(assetsPath).map(fileName => {
|
||||
const stats = fs.statSync(path.join(assetsPath, fileName));
|
||||
return {
|
||||
name: fileName,
|
||||
lastMod: stats.mtimeMs,
|
||||
};
|
||||
}).sort((a, b) => b.lastMod - a.lastMod).map(info => info.name);
|
||||
|
||||
const regex = /^(.+)[\-\.]([a-f0-9]+)\.(.+)$/i;
|
||||
const counts = {};
|
||||
|
||||
for(const fileName of files) {
|
||||
const match = fileName.match(regex);
|
||||
if(match) {
|
||||
const name = match[1] + '-' + match[3];
|
||||
counts[name] = (counts[name] || 0) + 1;
|
||||
|
||||
if(counts[name] > 5)
|
||||
fs.unlinkSync(path.join(assetsPath, fileName));
|
||||
} else console.log(`Encountered file name in assets folder with unexpected format: ${fileName}`);
|
||||
}
|
||||
};
|
35
src/utils.js
Normal file
35
src/utils.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
const crypto = require('crypto');
|
||||
|
||||
exports.strtr = (str, replacements) => str.toString().replace(
|
||||
/{([^}]+)}/g, (match, key) => replacements[key] || match
|
||||
);
|
||||
|
||||
const trim = function(str, chars, flags) {
|
||||
if(chars === undefined)
|
||||
chars = " \n\r\t\v\0";
|
||||
|
||||
let start = 0,
|
||||
end = str.length;
|
||||
|
||||
if(flags & 0x01)
|
||||
while(start < end && chars.indexOf(str[start]) >= 0)
|
||||
++start;
|
||||
|
||||
if(flags & 0x02)
|
||||
while(end > start && chars.indexOf(str[end - 1]) >= 0)
|
||||
--end;
|
||||
|
||||
return (start > 0 || end < str.length)
|
||||
? str.substring(start, end)
|
||||
: str;
|
||||
};
|
||||
|
||||
exports.trimStart = (str, chars) => trim(str, chars, 0x01);
|
||||
exports.trimEnd = (str, chars) => trim(str, chars, 0x02);
|
||||
exports.trim = (str, chars) => trim(str, chars, 0x03);
|
||||
|
||||
exports.shortHash = function(text) {
|
||||
const hash = crypto.createHash('sha256');
|
||||
hash.update(text);
|
||||
return hash.digest('hex').substring(0, 8);
|
||||
};
|
Loading…
Reference in a new issue