mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
move makeItem into option and command and fix click select
This commit is contained in:
@@ -46,4 +46,148 @@ export class SlashCommand {
|
|||||||
}
|
}
|
||||||
return `<span class="monospace">/${this.name}</span> ${this.helpString}${aliases}`;
|
return `<span class="monospace">/${this.name}</span> ${this.helpString}${aliases}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return li;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -107,158 +107,18 @@ export class SlashCommandAutoComplete {
|
|||||||
// init by appending all command options
|
// init by appending all command options
|
||||||
Object.keys(this.parser.commands).forEach(key=>{
|
Object.keys(this.parser.commands).forEach(key=>{
|
||||||
const cmd = this.parser.commands[key];
|
const cmd = this.parser.commands[key];
|
||||||
this.items[key] = this.makeItem(
|
this.items[key] = this.makeItem(new SlashCommandAutoCompleteOption(OPTION_TYPE.COMMAND, cmd, key));
|
||||||
key,
|
|
||||||
'/',
|
|
||||||
false,
|
|
||||||
cmd.namedArgumentList,
|
|
||||||
cmd.unnamedArgumentList,
|
|
||||||
cmd.returns,
|
|
||||||
cmd.helpString,
|
|
||||||
[cmd.name, ...(cmd.aliases ?? [])].filter(it=>it != key),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeItem(key, typeIcon, noSlash, namedArguments = [], unnamedArguments = [], returnType = 'void', helpString = '', aliasList = []) {
|
/**
|
||||||
const li = document.createElement('li'); {
|
*
|
||||||
li.classList.add('item');
|
* @param {SlashCommandAutoCompleteOption} option
|
||||||
const type = document.createElement('span'); {
|
* @returns
|
||||||
type.classList.add('type');
|
*/
|
||||||
type.classList.add('monospace');
|
makeItem(option) {
|
||||||
type.textContent = typeIcon;
|
const li = option.renderItem();
|
||||||
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 = noSlash ? '' : '/';
|
|
||||||
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 namedArguments) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const arg of unnamedArguments) {
|
|
||||||
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 = returnType ?? '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 = helpString;
|
|
||||||
const text = content.textContent;
|
|
||||||
content.innerHTML = '';
|
|
||||||
content.textContent = text;
|
|
||||||
help.append(content);
|
|
||||||
}
|
|
||||||
li.append(help);
|
|
||||||
}
|
|
||||||
if (aliasList.length > 0) {
|
|
||||||
const aliases = document.createElement('span'); {
|
|
||||||
aliases.classList.add('aliases');
|
|
||||||
aliases.append(' (alias: ');
|
|
||||||
for (const aliasName of aliasList) {
|
|
||||||
const alias = document.createElement('span'); {
|
|
||||||
alias.classList.add('monospace');
|
|
||||||
alias.textContent = `/${aliasName}`;
|
|
||||||
aliases.append(alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aliases.append(')');
|
|
||||||
// li.append(aliases);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// gotta listen to pointerdown (happens before textarea-blur)
|
// gotta listen to pointerdown (happens before textarea-blur)
|
||||||
li.addEventListener('pointerdown', ()=>{
|
li.addEventListener('pointerdown', ()=>{
|
||||||
// gotta catch pointerup to restore focus to textarea (blurs after pointerdown)
|
// gotta catch pointerup to restore focus to textarea (blurs after pointerdown)
|
||||||
@@ -269,9 +129,9 @@ export class SlashCommandAutoComplete {
|
|||||||
};
|
};
|
||||||
window.addEventListener('pointerup', resolver);
|
window.addEventListener('pointerup', resolver);
|
||||||
});
|
});
|
||||||
|
this.selectedItem = this.result.find(it=>it.name == li.getAttribute('data-name'));
|
||||||
this.select();
|
this.select();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
return li;
|
return li;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,11 +349,11 @@ export class SlashCommandAutoComplete {
|
|||||||
//TODO makeItem should be handled in the option class
|
//TODO makeItem should be handled in the option class
|
||||||
switch (option.type) {
|
switch (option.type) {
|
||||||
case OPTION_TYPE.QUICK_REPLY: {
|
case OPTION_TYPE.QUICK_REPLY: {
|
||||||
li = this.makeItem(option.name, 'QR', true);
|
li = this.makeItem(option);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPTION_TYPE.VARIABLE_NAME: {
|
case OPTION_TYPE.VARIABLE_NAME: {
|
||||||
li = this.makeItem(option.name, '𝑥', true);
|
li = this.makeItem(option);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPTION_TYPE.COMMAND: {
|
case OPTION_TYPE.COMMAND: {
|
||||||
|
@@ -47,6 +47,183 @@ export class SlashCommandAutoCompleteOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
renderItem() {
|
||||||
|
let li;
|
||||||
|
switch (this.type) {
|
||||||
|
case OPTION_TYPE.COMMAND: {
|
||||||
|
/**@type {SlashCommand}*/
|
||||||
|
// @ts-ignore
|
||||||
|
const cmd = this.value;
|
||||||
|
li = cmd.renderHelpItem();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPTION_TYPE.QUICK_REPLY: {
|
||||||
|
li = this.makeItem(this.name, 'QR', true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPTION_TYPE.VARIABLE_NAME: {
|
||||||
|
li = this.makeItem(this.name, '𝑥', true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li.setAttribute('data-name', this.name);
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
makeItem(key, typeIcon, noSlash, namedArguments = [], unnamedArguments = [], returnType = 'void', helpString = '', aliasList = []) {
|
||||||
|
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 = noSlash ? '' : '/';
|
||||||
|
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 namedArguments) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const arg of unnamedArguments) {
|
||||||
|
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 = returnType ?? '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 = helpString;
|
||||||
|
const text = content.textContent;
|
||||||
|
content.innerHTML = '';
|
||||||
|
content.textContent = text;
|
||||||
|
help.append(content);
|
||||||
|
}
|
||||||
|
li.append(help);
|
||||||
|
}
|
||||||
|
if (aliasList.length > 0) {
|
||||||
|
const aliases = document.createElement('span'); {
|
||||||
|
aliases.classList.add('aliases');
|
||||||
|
aliases.append(' (alias: ');
|
||||||
|
for (const aliasName of aliasList) {
|
||||||
|
const alias = document.createElement('span'); {
|
||||||
|
alias.classList.add('monospace');
|
||||||
|
alias.textContent = `/${aliasName}`;
|
||||||
|
aliases.append(alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aliases.append(')');
|
||||||
|
// li.append(aliases);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// gotta listen to pointerdown (happens before textarea-blur)
|
||||||
|
li.addEventListener('pointerdown', ()=>{
|
||||||
|
// gotta catch pointerup to restore focus to textarea (blurs after pointerdown)
|
||||||
|
this.pointerup = new Promise(resolve=>{
|
||||||
|
const resolver = ()=>{
|
||||||
|
window.removeEventListener('pointerup', resolver);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
window.addEventListener('pointerup', resolver);
|
||||||
|
});
|
||||||
|
this.select();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
renderDetails() {
|
renderDetails() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case OPTION_TYPE.COMMAND: {
|
case OPTION_TYPE.COMMAND: {
|
||||||
|
Reference in New Issue
Block a user