Move string utils to shared module
| @@ -7,7 +7,7 @@ import { ARGUMENT_TYPE, SlashCommandArgument } from '../../slash-commands/SlashC | |||
| 7 | import { enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; | 7 | import { enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 8 | import { enumTypes, SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js'; | 8 | import { enumTypes, SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js'; |
| 9 | import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; | 9 | import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; |
| 10 | import { uuidv4 } from '../../utils.js'; | 10 | import { collapseSpaces, getUniqueName, uuidv4 } from '../../utils.js'; |
| 11 | 11 | ||
| 12 | const MODULE_NAME = 'connection-manager'; | 12 | const MODULE_NAME = 'connection-manager'; |
| 13 | const NONE = '<None>'; | 13 | const NONE = '<None>'; |
| @@ -71,8 +71,6 @@ const profilesProvider = () => [ | |||
| 71 | */ | 71 | */ |
| 72 | 72 | ||
| 73 | const escapeArgument = (a) => a.replace(/"/g, '\\"').replace(/\|/g, '\\|'); | 73 | const escapeArgument = (a) => a.replace(/"/g, '\\"').replace(/\|/g, '\\|'); |
| 74 | const collapseSpaces = (s) => s.replace(/\s+/g, ' ').trim(); | ||
| 75 | const makeUnique = (s, f, i) => { if (!f(s)) { return s; } else { while (f(`${s} (${i})`)) { i++; } return `${s} (${i})`; } }; | ||
| 76 | 74 | ||
| 77 | /** | 75 | /** |
| 78 | * Finds the best match for the search value. | 76 | * Finds the best match for the search value. |
| @@ -150,7 +148,7 @@ async function createConnectionProfile(forceName = null) { | |||
| 150 | const profileForDisplay = makeFancyProfile(profile); | 148 | const profileForDisplay = makeFancyProfile(profile); |
| 151 | const template = await renderExtensionTemplateAsync(MODULE_NAME, 'profile', { profile: profileForDisplay }); | 149 | const template = await renderExtensionTemplateAsync(MODULE_NAME, 'profile', { profile: profileForDisplay }); |
| 152 | const checkName = (n) => extension_settings.connectionManager.profiles.some(p => p.name === n); | 150 | const checkName = (n) => extension_settings.connectionManager.profiles.some(p => p.name === n); |
| 153 | const suggestedName = makeUnique(collapseSpaces(`${profile.api ?? ''} ${profile.model ?? ''} - ${profile.preset ?? ''}`), checkName, 1); | 151 | const suggestedName = getUniqueName(collapseSpaces(`${profile.api ?? ''} ${profile.model ?? ''} - ${profile.preset ?? ''}`), checkName); |
| 154 | const name = forceName ?? await callGenericPopup(template, POPUP_TYPE.INPUT, suggestedName, { rows: 2 }); | 152 | const name = forceName ?? await callGenericPopup(template, POPUP_TYPE.INPUT, suggestedName, { rows: 2 }); |
| 155 | 153 | ||
| 156 | if (!name) { | 154 | if (!name) { |
| @@ -1436,6 +1436,15 @@ export function uuidv4() { | |||
| 1436 | }); | 1436 | }); |
| 1437 | } | 1437 | } |
| 1438 | 1438 | ||
| 1439 | /** | ||
| 1440 | * Collapses multiple spaces in a strings into one. | ||
| 1441 | * @param {string} s String to process | ||
| 1442 | * @returns {string} String with collapsed spaces | ||
| 1443 | */ | ||
| 1444 | export function collapseSpaces(s) { | ||
| 1445 | return s.replace(/\s+/g, ' ').trim(); | ||
| 1446 | } | ||
| 1447 | |||
| 1439 | function postProcessText(text, collapse = true) { | 1448 | function postProcessText(text, collapse = true) { |
| 1440 | // Remove carriage returns | 1449 | // Remove carriage returns |
| 1441 | text = text.replace(/\r/g, ''); | 1450 | text = text.replace(/\r/g, ''); |
| @@ -2041,7 +2050,7 @@ export async function fetchFaFile(name) { | |||
| 2041 | style.remove(); | 2050 | style.remove(); |
| 2042 | return [...sheet.cssRules] | 2051 | return [...sheet.cssRules] |
| 2043 | .filter(rule => rule.style?.content) | 2052 | .filter(rule => rule.style?.content) |
| 2044 | .map(rule => rule.selectorText.split(/,\s*/).map(selector=>selector.split('::').shift().slice(1))) | 2053 | .map(rule => rule.selectorText.split(/,\s*/).map(selector => selector.split('::').shift().slice(1))) |
| 2045 | ; | 2054 | ; |
| 2046 | } | 2055 | } |
| 2047 | export async function fetchFa() { | 2056 | export async function fetchFa() { |
| @@ -2068,7 +2077,7 @@ export async function showFontAwesomePicker(customList = null) { | |||
| 2068 | qry.placeholder = 'Filter icons'; | 2077 | qry.placeholder = 'Filter icons'; |
| 2069 | qry.autofocus = true; | 2078 | qry.autofocus = true; |
| 2070 | const qryDebounced = debounce(() => { | 2079 | const qryDebounced = debounce(() => { |
| 2071 | const result = faList.filter(fa => fa.find(className=>className.includes(qry.value.toLowerCase()))); | 2080 | const result = faList.filter(fa => fa.find(className => className.includes(qry.value.toLowerCase()))); |
| 2072 | for (const fa of faList) { | 2081 | for (const fa of faList) { |
| 2073 | if (!result.includes(fa)) { | 2082 | if (!result.includes(fa)) { |
| 2074 | fas[fa].classList.add('hidden'); | 2083 | fas[fa].classList.add('hidden'); |
| @@ -2090,7 +2099,7 @@ export async function showFontAwesomePicker(customList = null) { | |||
| 2090 | opt.classList.add('menu_button'); | 2099 | opt.classList.add('menu_button'); |
| 2091 | opt.classList.add('fa-solid'); | 2100 | opt.classList.add('fa-solid'); |
| 2092 | opt.classList.add(fa[0]); | 2101 | opt.classList.add(fa[0]); |
| 2093 | opt.title = fa.map(it=>it.slice(3)).join(', '); | 2102 | opt.title = fa.map(it => it.slice(3)).join(', '); |
| 2094 | opt.dataset.result = POPUP_RESULT.AFFIRMATIVE.toString(); | 2103 | opt.dataset.result = POPUP_RESULT.AFFIRMATIVE.toString(); |
| 2095 | opt.addEventListener('click', () => value = fa[0]); | 2104 | opt.addEventListener('click', () => value = fa[0]); |
| 2096 | grid.append(opt); | 2105 | grid.append(opt); |