diff --git a/public/scripts/slash-commands/SlashCommand.js b/public/scripts/slash-commands/SlashCommand.js index 249c950b7..e5094095a 100644 --- a/public/scripts/slash-commands/SlashCommand.js +++ b/public/scripts/slash-commands/SlashCommand.js @@ -35,202 +35,252 @@ export class SlashCommand { /**@type {SlashCommandNamedArgument[]}*/ namedArgumentList = []; /**@type {SlashCommandArgument[]}*/ unnamedArgumentList = []; - get helpStringFormatted() { - let aliases = ''; - if (this.aliases?.length > 0) { - aliases = ' (alias: '; - aliases += this.aliases - .map(it=>`/${it}`) - .join(', ') - ; - aliases += ')'; - } - return `/${this.name} ${this.helpString}${aliases}`; - } + /**@type {Object.}*/ helpCache = {}; + /**@type {Object.}*/ helpDetailsCache = {}; renderHelpItem(key = null) { key = key ?? this.name; - const typeIcon = '/'; - const li = document.createElement('li'); { - li.classList.add('item'); - const type = document.createElement('span'); { - type.classList.add('type'); - type.classList.add('monospace'); - type.textContent = typeIcon; - li.append(type); - } - const specs = document.createElement('span'); { - specs.classList.add('specs'); - const name = document.createElement('span'); { - name.classList.add('name'); - name.classList.add('monospace'); - name.textContent = '/'; - key.split('').forEach(char=>{ - const span = document.createElement('span'); { - span.textContent = char; - name.append(span); - } - }); - specs.append(name); + if (!this.helpCache[key]) { + const typeIcon = '/'; + const li = document.createElement('li'); { + li.classList.add('item'); + const type = document.createElement('span'); { + type.classList.add('type'); + type.classList.add('monospace'); + type.textContent = typeIcon; + li.append(type); } - const body = document.createElement('span'); { - body.classList.add('body'); - const args = document.createElement('span'); { - args.classList.add('arguments'); - for (const arg of this.namedArgumentList) { - const argItem = document.createElement('span'); { - argItem.classList.add('argument'); - argItem.classList.add('namedArgument'); - if (!arg.isRequired || (arg.defaultValue ?? false)) argItem.classList.add('optional'); - if (arg.acceptsMultiple) argItem.classList.add('multiple'); - const name = document.createElement('span'); { - name.classList.add('argument-name'); - name.textContent = arg.name; - argItem.append(name); - } - if (arg.enumList.length > 0) { - const enums = document.createElement('span'); { - enums.classList.add('argument-enums'); - for (const e of arg.enumList) { - const enumItem = document.createElement('span'); { - enumItem.classList.add('argument-enum'); - enumItem.textContent = e; - enums.append(enumItem); - } - } - argItem.append(enums); - } - } else { - const types = document.createElement('span'); { - types.classList.add('argument-types'); - for (const t of arg.typeList) { - const type = document.createElement('span'); { - type.classList.add('argument-type'); - type.textContent = t; - types.append(type); - } - } - argItem.append(types); - } - } - args.append(argItem); + const specs = document.createElement('span'); { + specs.classList.add('specs'); + const name = document.createElement('span'); { + name.classList.add('name'); + name.classList.add('monospace'); + name.textContent = '/'; + key.split('').forEach(char=>{ + const span = document.createElement('span'); { + span.textContent = char; + name.append(span); } - } - for (const arg of this.unnamedArgumentList) { - const argItem = document.createElement('span'); { - argItem.classList.add('argument'); - argItem.classList.add('unnamedArgument'); - if (!arg.isRequired || (arg.defaultValue ?? false)) argItem.classList.add('optional'); - if (arg.acceptsMultiple) argItem.classList.add('multiple'); - if (arg.enumList.length > 0) { - const enums = document.createElement('span'); { - enums.classList.add('argument-enums'); - for (const e of arg.enumList) { - const enumItem = document.createElement('span'); { - enumItem.classList.add('argument-enum'); - enumItem.textContent = e; - enums.append(enumItem); - } - } - argItem.append(enums); - } - } else { - const types = document.createElement('span'); { - types.classList.add('argument-types'); - for (const t of arg.typeList) { - const type = document.createElement('span'); { - type.classList.add('argument-type'); - type.textContent = t; - types.append(type); - } - } - argItem.append(types); - } - } - args.append(argItem); - } - } - body.append(args); + }); + specs.append(name); } - const returns = document.createElement('span'); { - returns.classList.add('returns'); - returns.textContent = this.returns ?? 'void'; - body.append(returns); - } - specs.append(body); - } - li.append(specs); - } - const help = document.createElement('span'); { - help.classList.add('help'); - const content = document.createElement('span'); { - content.classList.add('helpContent'); - content.innerHTML = this.helpString; - const text = content.textContent; - content.innerHTML = ''; - content.textContent = text; - help.append(content); - } - li.append(help); - } - if (this.aliases.length > 0) { - const aliases = document.createElement('span'); { - aliases.classList.add('aliases'); - aliases.append(' (alias: '); - for (const aliasName of this.aliases) { - const alias = document.createElement('span'); { - alias.classList.add('monospace'); - alias.textContent = `/${aliasName}`; - aliases.append(alias); - } - } - aliases.append(')'); - // li.append(aliases); - } - } - } - return li; - } - - renderHelpDetails(key = null) { - const frag = document.createDocumentFragment(); - key = key ?? this.name; - const cmd = this; - const namedArguments = cmd.namedArgumentList ?? []; - const unnamedArguments = cmd.unnamedArgumentList ?? []; - const returnType = cmd.returns ?? 'void'; - const helpString = cmd.helpString ?? 'NO DETAILS'; - const aliasList = [cmd.name, ...(cmd.aliases ?? [])].filter(it=>it != key); - const specs = document.createElement('div'); { - specs.classList.add('specs'); - const name = document.createElement('div'); { - name.classList.add('name'); - name.classList.add('monospace'); - name.title = 'command name'; - name.textContent = `/${key}`; - specs.append(name); - } - const body = document.createElement('div'); { - body.classList.add('body'); - const args = document.createElement('ul'); { - args.classList.add('arguments'); - for (const arg of namedArguments) { - const listItem = document.createElement('li'); { - listItem.classList.add('argumentItem'); - const argSpec = document.createElement('div'); { - argSpec.classList.add('argumentSpec'); - const argItem = document.createElement('div'); { + const body = document.createElement('span'); { + body.classList.add('body'); + const args = document.createElement('span'); { + args.classList.add('arguments'); + for (const arg of this.namedArgumentList) { + const argItem = document.createElement('span'); { argItem.classList.add('argument'); argItem.classList.add('namedArgument'); - argItem.title = `${arg.isRequired ? '' : 'optional '}named argument`; if (!arg.isRequired || (arg.defaultValue ?? false)) argItem.classList.add('optional'); if (arg.acceptsMultiple) argItem.classList.add('multiple'); const name = document.createElement('span'); { name.classList.add('argument-name'); - name.title = `${argItem.title} - name`; name.textContent = arg.name; argItem.append(name); } + if (arg.enumList.length > 0) { + const enums = document.createElement('span'); { + enums.classList.add('argument-enums'); + for (const e of arg.enumList) { + const enumItem = document.createElement('span'); { + enumItem.classList.add('argument-enum'); + enumItem.textContent = e; + enums.append(enumItem); + } + } + argItem.append(enums); + } + } else { + const types = document.createElement('span'); { + types.classList.add('argument-types'); + for (const t of arg.typeList) { + const type = document.createElement('span'); { + type.classList.add('argument-type'); + type.textContent = t; + types.append(type); + } + } + argItem.append(types); + } + } + args.append(argItem); + } + } + for (const arg of this.unnamedArgumentList) { + const argItem = document.createElement('span'); { + argItem.classList.add('argument'); + argItem.classList.add('unnamedArgument'); + if (!arg.isRequired || (arg.defaultValue ?? false)) argItem.classList.add('optional'); + if (arg.acceptsMultiple) argItem.classList.add('multiple'); + if (arg.enumList.length > 0) { + const enums = document.createElement('span'); { + enums.classList.add('argument-enums'); + for (const e of arg.enumList) { + const enumItem = document.createElement('span'); { + enumItem.classList.add('argument-enum'); + enumItem.textContent = e; + enums.append(enumItem); + } + } + argItem.append(enums); + } + } else { + const types = document.createElement('span'); { + types.classList.add('argument-types'); + for (const t of arg.typeList) { + const type = document.createElement('span'); { + type.classList.add('argument-type'); + type.textContent = t; + types.append(type); + } + } + argItem.append(types); + } + } + args.append(argItem); + } + } + body.append(args); + } + const returns = document.createElement('span'); { + returns.classList.add('returns'); + returns.textContent = this.returns ?? 'void'; + body.append(returns); + } + specs.append(body); + } + li.append(specs); + } + const help = document.createElement('span'); { + help.classList.add('help'); + const content = document.createElement('span'); { + content.classList.add('helpContent'); + content.innerHTML = this.helpString; + const text = content.textContent; + content.innerHTML = ''; + content.textContent = text; + help.append(content); + } + li.append(help); + } + if (this.aliases.length > 0) { + const aliases = document.createElement('span'); { + aliases.classList.add('aliases'); + aliases.append(' (alias: '); + for (const aliasName of this.aliases) { + const alias = document.createElement('span'); { + alias.classList.add('monospace'); + alias.textContent = `/${aliasName}`; + aliases.append(alias); + } + } + aliases.append(')'); + // li.append(aliases); + } + } + } + this.helpCache[key] = li; + } + return this.helpCache[key]; + } + + renderHelpDetails(key = null) { + key = key ?? this.name; + if (!this.helpDetailsCache[key]) { + const frag = document.createDocumentFragment(); + const cmd = this; + const namedArguments = cmd.namedArgumentList ?? []; + const unnamedArguments = cmd.unnamedArgumentList ?? []; + const returnType = cmd.returns ?? 'void'; + const helpString = cmd.helpString ?? 'NO DETAILS'; + const aliasList = [cmd.name, ...(cmd.aliases ?? [])].filter(it=>it != key); + const specs = document.createElement('div'); { + specs.classList.add('specs'); + const name = document.createElement('div'); { + name.classList.add('name'); + name.classList.add('monospace'); + name.title = 'command name'; + name.textContent = `/${key}`; + specs.append(name); + } + const body = document.createElement('div'); { + body.classList.add('body'); + const args = document.createElement('ul'); { + args.classList.add('arguments'); + for (const arg of namedArguments) { + const listItem = document.createElement('li'); { + listItem.classList.add('argumentItem'); + const argSpec = document.createElement('div'); { + argSpec.classList.add('argumentSpec'); + const argItem = document.createElement('div'); { + argItem.classList.add('argument'); + argItem.classList.add('namedArgument'); + argItem.title = `${arg.isRequired ? '' : 'optional '}named argument`; + if (!arg.isRequired || (arg.defaultValue ?? false)) argItem.classList.add('optional'); + if (arg.acceptsMultiple) argItem.classList.add('multiple'); + const name = document.createElement('span'); { + name.classList.add('argument-name'); + name.title = `${argItem.title} - name`; + name.textContent = arg.name; + argItem.append(name); + } + if (arg.enumList.length > 0) { + const enums = document.createElement('span'); { + enums.classList.add('argument-enums'); + enums.title = `${argItem.title} - accepted values`; + for (const e of arg.enumList) { + const enumItem = document.createElement('span'); { + enumItem.classList.add('argument-enum'); + enumItem.textContent = e; + enums.append(enumItem); + } + } + argItem.append(enums); + } + } else { + const types = document.createElement('span'); { + types.classList.add('argument-types'); + types.title = `${argItem.title} - accepted types`; + for (const t of arg.typeList) { + const type = document.createElement('span'); { + type.classList.add('argument-type'); + type.textContent = t; + types.append(type); + } + } + argItem.append(types); + } + } + argSpec.append(argItem); + } + if (arg.defaultValue !== null) { + const argDefault = document.createElement('div'); { + argDefault.classList.add('argument-default'); + argDefault.title = 'default value'; + argDefault.textContent = arg.defaultValue.toString(); + argSpec.append(argDefault); + } + } + listItem.append(argSpec); + } + const desc = document.createElement('div'); { + desc.classList.add('argument-description'); + desc.innerHTML = arg.description; + listItem.append(desc); + } + args.append(listItem); + } + } + for (const arg of unnamedArguments) { + const listItem = document.createElement('li'); { + listItem.classList.add('argumentItem'); + const argItem = document.createElement('div'); { + argItem.classList.add('argument'); + argItem.classList.add('unnamedArgument'); + argItem.title = `${arg.isRequired ? '' : 'optional '}unnamed argument`; + if (!arg.isRequired || (arg.defaultValue ?? false)) argItem.classList.add('optional'); + if (arg.acceptsMultiple) argItem.classList.add('multiple'); if (arg.enumList.length > 0) { const enums = document.createElement('span'); { enums.classList.add('argument-enums'); @@ -258,106 +308,52 @@ export class SlashCommand { argItem.append(types); } } - argSpec.append(argItem); + listItem.append(argItem); } - if (arg.defaultValue !== null) { - const argDefault = document.createElement('div'); { - argDefault.classList.add('argument-default'); - argDefault.title = 'default value'; - argDefault.textContent = arg.defaultValue.toString(); - argSpec.append(argDefault); - } + const desc = document.createElement('div'); { + desc.classList.add('argument-description'); + desc.innerHTML = arg.description; + listItem.append(desc); } - listItem.append(argSpec); + args.append(listItem); } - const desc = document.createElement('div'); { - desc.classList.add('argument-description'); - desc.innerHTML = arg.description; - listItem.append(desc); - } - args.append(listItem); + } + body.append(args); + } + const returns = document.createElement('span'); { + returns.classList.add('returns'); + returns.title = [null, undefined, 'void'].includes(returnType) ? 'command does not return anything' : 'return value'; + returns.textContent = returnType ?? 'void'; + body.append(returns); + } + specs.append(body); + } + frag.append(specs); + } + const help = document.createElement('span'); { + help.classList.add('help'); + help.innerHTML = helpString; + for (const code of help.querySelectorAll('pre > code')) { + code.classList.add('language-stscript'); + hljs.highlightElement(code); + } + frag.append(help); + } + if (aliasList.length > 0) { + const aliases = document.createElement('span'); { + aliases.classList.add('aliases'); + for (const aliasName of aliasList) { + const alias = document.createElement('span'); { + alias.classList.add('alias'); + alias.textContent = `/${aliasName}`; + aliases.append(alias); } } - for (const arg of unnamedArguments) { - const listItem = document.createElement('li'); { - listItem.classList.add('argumentItem'); - const argItem = document.createElement('div'); { - argItem.classList.add('argument'); - argItem.classList.add('unnamedArgument'); - argItem.title = `${arg.isRequired ? '' : 'optional '}unnamed argument`; - if (!arg.isRequired || (arg.defaultValue ?? false)) argItem.classList.add('optional'); - if (arg.acceptsMultiple) argItem.classList.add('multiple'); - if (arg.enumList.length > 0) { - const enums = document.createElement('span'); { - enums.classList.add('argument-enums'); - enums.title = `${argItem.title} - accepted values`; - for (const e of arg.enumList) { - const enumItem = document.createElement('span'); { - enumItem.classList.add('argument-enum'); - enumItem.textContent = e; - enums.append(enumItem); - } - } - argItem.append(enums); - } - } else { - const types = document.createElement('span'); { - types.classList.add('argument-types'); - types.title = `${argItem.title} - accepted types`; - for (const t of arg.typeList) { - const type = document.createElement('span'); { - type.classList.add('argument-type'); - type.textContent = t; - types.append(type); - } - } - argItem.append(types); - } - } - listItem.append(argItem); - } - const desc = document.createElement('div'); { - desc.classList.add('argument-description'); - desc.innerHTML = arg.description; - listItem.append(desc); - } - args.append(listItem); - } - } - body.append(args); + frag.append(aliases); } - const returns = document.createElement('span'); { - returns.classList.add('returns'); - returns.title = [null, undefined, 'void'].includes(returnType) ? 'command does not return anything' : 'return value'; - returns.textContent = returnType ?? 'void'; - body.append(returns); - } - specs.append(body); } - frag.append(specs); + this.helpDetailsCache[key] = frag; } - const help = document.createElement('span'); { - help.classList.add('help'); - help.innerHTML = helpString; - for (const code of help.querySelectorAll('pre > code')) { - code.classList.add('language-stscript'); - hljs.highlightElement(code); - } - frag.append(help); - } - if (aliasList.length > 0) { - const aliases = document.createElement('span'); { - aliases.classList.add('aliases'); - for (const aliasName of aliasList) { - const alias = document.createElement('span'); { - alias.classList.add('alias'); - alias.textContent = `/${aliasName}`; - aliases.append(alias); - } - } - frag.append(aliases); - } - } - return frag; + return this.helpDetailsCache[key].cloneNode(true); } }