mirror of
https://github.com/motajs/template.git
synced 2026-11-02 06:34:31 +08:00
init: 2.B
This commit is contained in:
commit
6bf32174d8
610 files changed
+151444
No files matched your search
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "@motajs/common"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './logger';
|
||||
export * from './utils';
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"error": {
|
||||
"1": "Unexpected error when posting danmaku. Error info: $1",
|
||||
"2": "Unexpected loading error in loading resource '$1/$2'. Error info: $3",
|
||||
"3": "Syntax error in parsing CSS: Unexpected ':'. Col: $1. CSS string: '$2'",
|
||||
"4": "Syntax error in parsing CSS: Unexpected ';'. Col: $1. CSS string: '$2'",
|
||||
"5": "Syntax error in parsing CSS: Missing property name after '-'. Col: $1. CSS string: '$2'",
|
||||
"6": "Syntax error in parsing CSS: Unexpected end of css, expecting ':'. Col: $1. CSS string: '$2'",
|
||||
"7": "Syntax error in parsing CSS: Unexpected end of css, expecting property value. Col: $1. CSS string: '$2'",
|
||||
"8": "Post danmaku with not allowed css. Info: $1",
|
||||
"9": "Cannot initialize shader program. Error info: $1",
|
||||
"10": "Cannot compile $1 shader. Error info: $2",
|
||||
"11": "Cache depth cannot larger than 31.",
|
||||
"12": "Cannot move while status is not 'moving'. Call 'readyMove' first.",
|
||||
"13": "Cannot compile $1 shader. Error info: $2",
|
||||
"14": "",
|
||||
"15": "",
|
||||
"16": "Cannot find log message for $1 code $2.",
|
||||
"17": "Cannot use shader program for shader element that does not belong to it.",
|
||||
"18": "Cannot delete shader program for shader element that does not belong to it.",
|
||||
"19": "Cannot create MotaRenderer instance for nonexistent canvas.",
|
||||
"20": "Cannot create render element for tag '$1', since there's no registration for it.",
|
||||
"21": "Incorrect render prop type is delivered. key: '$1', expected type: '$2', delivered type: '$3'",
|
||||
"22": "Incorrect props for custom tag. Please ensure you have delivered 'item' prop and other required props.",
|
||||
"23": "Cannot get reader when fetching '$1'.",
|
||||
"24": "Cannot decode source type of '$1', since there is no registered decoder for that type.",
|
||||
"25": "Unknown audio type. Header: '$1'",
|
||||
"26": "Uncaught error when fetching stream data from '$1'. Error info: $2.",
|
||||
"1201": "Floor-damage extension needs 'floor-binder' extension as dependency."
|
||||
},
|
||||
"warn": {
|
||||
"1": "Resource with type of 'none' is loaded.",
|
||||
"2": "Repeat load of resource '$1/$2'.",
|
||||
"3": "Unknown danmaku tag: $1",
|
||||
"4": "Ignored a mismatched ']' in danmaku.",
|
||||
"5": "Repeat post danmaku.",
|
||||
"6": "Registered special danmaku element: $1.",
|
||||
"7": "Unknown special danmaku element: '$1'.",
|
||||
"8": "Incomplete render data is put. None will be filled to the lacked data.",
|
||||
"9": "Data transfered is partially (or totally) out of range. Overflowed data will be ignored.",
|
||||
"10": "Cannot resolve big image of enemy '$1'.",
|
||||
"11": "Cannot resolve material $1. Material not exists.",
|
||||
"12": "Cannot mark buffable with a non-number status. Key: '$1'.",
|
||||
"13": "Cannot set buff of non-number status. Key: '$1'.",
|
||||
"14": "Cannot add status of non-number status. Key: '$1'.",
|
||||
"15": "Cannot get item of a non-item block on loc: $1,$2,$3.",
|
||||
"16": "Override repeated state key: '$1'.",
|
||||
"17": "Floor-damage extension needs 'floor-binder' extension as dependency.",
|
||||
"18": "Uncaught error in posting like info for danmaku. Danmaku id: $1.",
|
||||
"19": "Repeat light id: '$1'.",
|
||||
"20": "Cannot apply animation to camera operation that does not belong to it.",
|
||||
"21": "Cannot apply transition to camera operation that does not belong to it.",
|
||||
"22": "There is already an active camera for delivered render item. Consider using 'Camera.for' or disable the active camera to avoid some exceptions.",
|
||||
"23": "Render item with id of '$1' has already exists. Please avoid repeat id since it may cause issues when use 'getElementById'.",
|
||||
"24": "Uniform block can only be used in glsl version es 300.",
|
||||
"25": "Cannot activate weather since there's no weather named '$1'.",
|
||||
"26": "Cannot set attribute when only element number specified. Use 'pointer' or 'pointerI' instead.",
|
||||
"27": "Cannot vertex attribute integer point when specified as float. Use 'set' or 'pointer' instead.",
|
||||
"28": "Redefinition of shader $1: '$2'",
|
||||
"29": "Cannot define new texture since texture index is larger than max texture count.",
|
||||
"30": "Cannot use indices named $1 since no definition for it. Please define it in advance.",
|
||||
"31": "Cannot use indices since the indices instance is not belong to the program.",
|
||||
"32": "Sub-image exceeds texture dimensions, auto adjusting size.",
|
||||
"33": "Cannot modify MotaOffscreenCanvas2D that is freezed.",
|
||||
"34": "Repeated render tag registration: '$1'.",
|
||||
"35": "Cannot append child on plain render item, please ensure you have overrided 'appendChild' method in your own element.",
|
||||
"36": "Cannot remove child on plain render item, please ensure you have overrided 'removeChild' method in your own element.",
|
||||
"37": "Cannot execute 'requestSort' on plain render item, please ensure you have overrided 'requestSort' method in your own element.",
|
||||
"38": "Using plain text in jsx is strongly not recommended, since you can hardly modify its attributes. Consider using Text element instead.",
|
||||
"39": "Plain text is not supported outside Text element.",
|
||||
"40": "Cannot return canvas that is not provided by this pool.",
|
||||
"41": "Width of text content components must be positive. receive: $1",
|
||||
"42": "Repeated Textbox id: '$1'.",
|
||||
"43": "Cannot set icon of '$1', since it does not exists. Please ensure you have delivered correct icon id or number.",
|
||||
"44": "Unexpected end when loading stream audio, reason: '$1'",
|
||||
"45": "Audio route with id of '$1' has already existed. New route will override old route.",
|
||||
"46": "Cannot pipe new StreamReader object when stream is loading.",
|
||||
"47": "Audio stream decoder for audio type '$1' has already existed.",
|
||||
"48": "Sample rate in stream audio must be constant.",
|
||||
"49": "Repeated patch for '$1', key: '$2'.",
|
||||
"50": "Unknown audio extension name: '$1'",
|
||||
"51": "Cannot decode sound '$1', since audio file may not supported by 2.b.",
|
||||
"52": "Cannot play sound '$1', since there is no added data named it.",
|
||||
"53": "Cannot $1 audio route '$2', since there is not added route named it.",
|
||||
"54": "Missing start tag for '$1', index: $2.",
|
||||
"55": "Unchildable tag '$1' should follow with param.",
|
||||
"56": "Method '$1' has been deprecated. Consider using '$2' instead.",
|
||||
"57": "Repeated UI controller id '$1'.",
|
||||
"58": "Fail to set ellipse round rect, since length of 'ellipse' property should only be 2, 4, 6 or 8. delivered: $1",
|
||||
"59": "Unknown icon '$1' in parsing text content.",
|
||||
"60": "Repeated Tip id: '$1'.",
|
||||
"61": "Unexpected recursive call of $1.update?$2 in render function. Please ensure you have to do this, if you do, ignore this warn.",
|
||||
"62": "Recursive fallback fonts in '$1'.",
|
||||
"63": "Uncaught promise error in waiting box component. Error reason: $1",
|
||||
"64": "Text node type and block type mismatch: '$1' vs '$2'",
|
||||
"65": "Cannot bind a weather controller twice.",
|
||||
"1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
import { debounce } from 'lodash-es';
|
||||
import logInfo from './logger.json';
|
||||
|
||||
export const enum LogLevel {
|
||||
/** 输出所有,包括日志 */
|
||||
LOG,
|
||||
/** 报错、严重警告和警告 */
|
||||
WARNING,
|
||||
/** 仅报错 */
|
||||
ERROR
|
||||
}
|
||||
|
||||
interface LoggerCatchInfo {
|
||||
code?: number;
|
||||
level: LogLevel;
|
||||
message: string;
|
||||
}
|
||||
|
||||
interface LoggerCatchReturns<T> {
|
||||
ret: T;
|
||||
info: LoggerCatchInfo[];
|
||||
}
|
||||
|
||||
let logTip: HTMLSpanElement;
|
||||
if (!main.replayChecking) {
|
||||
const tip = document.createElement('span');
|
||||
logTip = tip;
|
||||
tip.style.position = 'fixed';
|
||||
tip.style.right = '0';
|
||||
tip.style.bottom = '0';
|
||||
tip.style.height = '20px';
|
||||
tip.style.width = 'auto';
|
||||
tip.style.textAlign = 'right';
|
||||
tip.style.padding = '0 5px';
|
||||
tip.style.fontSize = '16px';
|
||||
tip.style.fontFamily = 'Arial';
|
||||
tip.style.display = 'none';
|
||||
tip.style.margin = '2px';
|
||||
document.body.appendChild(tip);
|
||||
}
|
||||
|
||||
const hideTipText = debounce(() => {
|
||||
if (main.replayChecking) return;
|
||||
logTip.style.display = 'none';
|
||||
}, 5000);
|
||||
|
||||
const nums = new Set('1234567890');
|
||||
|
||||
export interface ILoggerInfo {
|
||||
error: Record<number, string>;
|
||||
warn: Record<number, string>;
|
||||
}
|
||||
|
||||
export class Logger {
|
||||
enabled: boolean = true;
|
||||
|
||||
private catching: boolean = false;
|
||||
private catchedInfo: LoggerCatchInfo[] = [];
|
||||
|
||||
private catchStack: LoggerCatchInfo[][] = [];
|
||||
|
||||
constructor(
|
||||
public readonly level: LogLevel,
|
||||
public readonly info: ILoggerInfo
|
||||
) {}
|
||||
|
||||
private parseInfo(text: string, ...params: string[]) {
|
||||
let pointer = -1;
|
||||
let str = '';
|
||||
|
||||
let inParam = false;
|
||||
let paramNum = '';
|
||||
while (++pointer < text.length) {
|
||||
const char = text[pointer];
|
||||
|
||||
if (char === '$' && text[pointer - 1] !== '\\') {
|
||||
inParam = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inParam) {
|
||||
if (nums.has(char)) {
|
||||
paramNum += char;
|
||||
}
|
||||
if (!nums.has(text[pointer + 1])) {
|
||||
inParam = false;
|
||||
const num = Number(paramNum);
|
||||
paramNum = '';
|
||||
str += params[num - 1] ?? '[not delivered]';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
str += char;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出报错信息
|
||||
* @param code 错误代码,每个错误都应当使用唯一的错误代码
|
||||
* @param params 参数
|
||||
*/
|
||||
error(code: number, ...params: string[]) {
|
||||
const info = this.info.error[code];
|
||||
if (!info) {
|
||||
logger.error(16, 'error', code.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
const text = this.parseInfo(info, ...params);
|
||||
if (this.catching) {
|
||||
this.catchedInfo.push({
|
||||
level: LogLevel.ERROR,
|
||||
message: text,
|
||||
code
|
||||
});
|
||||
}
|
||||
if (this.level <= LogLevel.ERROR && this.enabled) {
|
||||
if (!main.replayChecking) {
|
||||
logTip.style.color = 'lightcoral';
|
||||
logTip.style.display = 'block';
|
||||
logTip.textContent = `Error thrown, please check in console.`;
|
||||
hideTipText();
|
||||
}
|
||||
const n = Math.floor(code / 50) + 1;
|
||||
const n2 = code % 50;
|
||||
const url = `${location.origin}/_docs/logger/error/error${n}.html#error-code-${n2}`;
|
||||
console.error(`[ERROR Code ${code}] ${text} See ${url}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出警告信息
|
||||
* @param code 警告代码
|
||||
* @param text 警告信息
|
||||
*/
|
||||
warn(code: number, ...params: string[]) {
|
||||
const info = this.info.warn[code];
|
||||
if (!info) {
|
||||
logger.error(16, 'warn', code.toString());
|
||||
return;
|
||||
}
|
||||
const text = this.parseInfo(info, ...params);
|
||||
|
||||
if (this.catching) {
|
||||
this.catchedInfo.push({
|
||||
level: LogLevel.ERROR,
|
||||
message: text,
|
||||
code
|
||||
});
|
||||
}
|
||||
if (this.level <= LogLevel.WARNING && this.enabled) {
|
||||
if (!main.replayChecking) {
|
||||
logTip.style.color = 'gold';
|
||||
logTip.style.display = 'block';
|
||||
logTip.textContent = `Warning thrown, please check in console.`;
|
||||
hideTipText();
|
||||
}
|
||||
const n = Math.floor(code / 50) + 1;
|
||||
const n2 = code % 50;
|
||||
const url = `${location.origin}/_docs/logger/warn/warn${n}.html#warn-code-${n2}`;
|
||||
console.warn(`[WARNING Code ${code}] ${text} See ${url}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出日志
|
||||
* @param text 日志信息
|
||||
*/
|
||||
log(text: string) {
|
||||
if (this.catching) {
|
||||
this.catchedInfo.push({
|
||||
level: LogLevel.ERROR,
|
||||
message: text
|
||||
});
|
||||
}
|
||||
if (this.level <= LogLevel.LOG && this.enabled) {
|
||||
console.log(`[LOG] ${text}`);
|
||||
}
|
||||
}
|
||||
|
||||
catch<T>(fn: () => T): LoggerCatchReturns<T> {
|
||||
const before = this.enabled;
|
||||
this.catchedInfo = [];
|
||||
this.catchStack.push(this.catchedInfo);
|
||||
this.disable();
|
||||
this.catching = true;
|
||||
const ret = fn();
|
||||
if (this.catchStack.length === 0) {
|
||||
this.catching = false;
|
||||
} else {
|
||||
this.catching = true;
|
||||
}
|
||||
if (before) this.enable();
|
||||
|
||||
this.catchStack.pop();
|
||||
const last = this.catchStack?.at(-1);
|
||||
const info = this.catchedInfo;
|
||||
this.catchedInfo = last ?? [];
|
||||
|
||||
return { ret, info };
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
export const logger = new Logger(LogLevel.LOG, logInfo);
|
||||
@@ -0,0 +1,3 @@
|
||||
export function sleep(time: number) {
|
||||
return new Promise(res => setTimeout(res, time));
|
||||
}
|
||||
Reference in new issue
Block a user