|
import { hljs } from '../../lib.js'; |
|
import { t } from '../i18n.js'; |
|
import { SlashCommandAbortController } from './SlashCommandAbortController.js'; |
|
import { SlashCommandArgument, SlashCommandNamedArgument } from './SlashCommandArgument.js'; |
|
import { SlashCommandClosure } from './SlashCommandClosure.js'; |
|
import { SlashCommandDebugController } from './SlashCommandDebugController.js'; |
|
import { SlashCommandScope } from './SlashCommandScope.js'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class SlashCommand { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static fromProps(props) { |
|
const instance = Object.assign(new this(), props); |
|
return instance; |
|
} |
|
|
|
|
|
|
|
|
|
name; |
|
callback; |
|
helpString; |
|
splitUnnamedArgument = false; |
|
splitUnnamedArgumentCount; |
|
rawQuotes = false; |
|
aliases = []; |
|
returns; |
|
namedArgumentList = []; |
|
unnamedArgumentList = []; |
|
|
|
helpCache = {}; |
|
helpDetailsCache = {}; |
|
|
|
isExtension = false; |
|
isThirdParty = false; |
|
source; |
|
|
|
renderHelpItem(key = null) { |
|
key = key ?? this.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 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); |
|
} |
|
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.value; |
|
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.value; |
|
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 stopgap = document.createElement('span'); { |
|
stopgap.classList.add('stopgap'); |
|
stopgap.textContent = ''; |
|
li.append(stopgap); |
|
} |
|
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(')'); |
|
|
|
} |
|
} |
|
} |
|
this.helpCache[key] = li; |
|
} |
|
return (this.helpCache[key].cloneNode(true)); |
|
} |
|
|
|
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 head = document.createElement('div'); { |
|
head.classList.add('head'); |
|
const name = document.createElement('div'); { |
|
name.classList.add('name'); |
|
name.classList.add('monospace'); |
|
name.title = 'command name'; |
|
name.textContent = `/${key}`; |
|
head.append(name); |
|
} |
|
const src = document.createElement('div'); { |
|
src.classList.add('source'); |
|
src.classList.add('fa-solid'); |
|
if (this.isExtension) { |
|
src.classList.add('isExtension'); |
|
src.classList.add('fa-cubes'); |
|
if (this.isThirdParty) src.classList.add('isThirdParty'); |
|
else src.classList.add('isCore'); |
|
} else { |
|
src.classList.add('isCore'); |
|
src.classList.add('fa-star-of-life'); |
|
} |
|
src.title = [ |
|
this.isExtension ? 'Extension' : 'Core', |
|
this.isThirdParty ? 'Third Party' : (this.isExtension ? 'Core' : null), |
|
this.source, |
|
].filter(it=>it).join('\n'); |
|
head.append(src); |
|
} |
|
if (this.rawQuotes) { |
|
const rawQuotes = document.createElement('div'); { |
|
rawQuotes.classList.add('rawQuotes'); |
|
rawQuotes.classList.add('fa-solid'); |
|
rawQuotes.classList.add('fa-quote-left'); |
|
rawQuotes.title = t`Does not alter quoted literal unnamed arguments. Pass raw=false argument to override.`; |
|
head.append(rawQuotes); |
|
} |
|
} |
|
specs.append(head); |
|
} |
|
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.value; |
|
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 argSpec = document.createElement('div'); { |
|
argSpec.classList.add('argumentSpec'); |
|
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.value; |
|
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); |
|
} |
|
} |
|
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); |
|
} |
|
} |
|
frag.append(aliases); |
|
} |
|
} |
|
this.helpDetailsCache[key] = frag; |
|
} |
|
const frag = document.createDocumentFragment(); |
|
frag.append(this.helpDetailsCache[key].cloneNode(true)); |
|
return frag; |
|
} |
|
} |
|
|