Files
Aurora.3/tgui/packages/common/string.js
Matt Atlas 31956c7eb0 Rock the UI Away - Removes VueUI and adds TGUI (#16509)
* tgui the beginning

* binaries and the like

* Bring in the last of it

* Example radio UI

* delete example

* NTOS Main Menu, start on manifest, tgui states

* tasks.json

* gunnery ui pt 1

* okay

* fix everything

* scss update

* oops

* manifest gigablast

* downloader part 1

* download prt 2

* NTOSDownloader final

* mfw committing to_worlds

* gunnery console pt2

* i cooked

* targeting (finished)

* one vueui down

* voting ui almost done

* MY MIND FEELS LIKE AN ARCH ENEMYYYY

* voting ui down

* photocopier

* ntos config + download fixes

* photocopier 2

* refactor define

* NTOS client manager + fixes

* fax machine final (it also uses toner now)

* marching forwards... left behind...

* ntnrc part 1

* canister

* add quotes

* portable pumps pt1 + more backgrounds

* oops

* finish the portable pump

* freezers

so I'll keep on pushing forward... you haven't seen the last of me... oooooooh...

* doors ui pt1

* finish doors UI (forgive me wildkins it's a bit of shitcode)

* vitals monitor, make things use labeled lists, new backgrounds

* mais j'envoyé aucun mayday...

* maglock pt1

* pour ça je me suis perdu...

* infrared

* fix that

* prox sensor pt1

* prox sensor

* signaler (this was actually pretty hard)

* atmos control pt1

* atmos control pt1.1

* atmos pt 2

* fuel injector

* multitool UI

* jammer

* list viewer

* APC

* portgen

* targeting console updates + SMES ui

* new themes, shield generator

* supermatter

* Add ore detector and (shitty) NTNet Relay

* orderterminal pt1

* orderterminal pt2

* smartfridge

* Add (air-)tank GUI update ore detector size

* Adds Transfer Valves

* Add AtmoScrubber

* analyzer pt1

* weapons analyzer pt2

* bodyscanner pt1

* bodyscanner pt2

* fix this shitcode

* seed storage

* appearance changer

* appearance changer final

* sleeper pt1

* sleeper

* gps

* vehicles

* chem dispenser

* lily request

* holopad

* tgui modules pt1

* ppanel

* damage menu

* fixes

* im here too now

* follow menu, search bars

* quikpay

* quikpay fixes

* circuit printer

* ppanel

* ppanel updates

* pai

* turret controls (i want to kill myself)

* tweak

* remove the boardgame

* guntracker

* implant tracker

* penal mechs

come close to me, come close to me

* chem codex

* pai radio

* doorjack

* pai directives

* signaler removal, sensors

* ghost spawner

* spawnpoint

* fixes

* teleporter

* one more to the chopping block

* account database

* remove divider

* scanner, atmos

* latejoin ui pt1

* latejoin

* records pt1

* RECORDS UI DONE

* delete interpreter & records

* CHAT FUCKING CLIENT

* data updates

* fix some things

* final UI, log

* basic nanoui fix

* antag panel

* remove vueui

* atm update

* vending update

* warrants, cameras

* ntmonitor

* time comes for all

* preserve this legacy

* bring that back (oops)

* rcon, ui auto update for computer UIs, remove rcon computers

* alarm monitoring (a bit broke and also todo: add custom alarm monitoring programs to a few consoles)

* A LIKE SUPREME

* a

* power monitor

* lights on

* fuck this code, fuck nanoui modules, and fuck nanoui

* LEAVE IT OH SO FAR BEHIND

* fix alarm monitoring for synths

* I SAW IN YOU WHAT LIFE WAS MISSING

* comms console

* idcard and record updates

* turn the light on

* arcade

* pt2

* news browser

* static

* crusher

* f

* COULD I JUST SLEIGH THE GOLD FROM THE BALLS? I'M SO FRUSTRATED OH COULD YOU TELL? IF I HEAR ONE MORE VUEUI OR ONE NANOUI I'M GONNA LOSE IT SO LET ME GOOOOOOOOOOOOOOOOO

* codeowners & suit sensors

* html ui style removal

* make lint happy

* resist and disorder

* i slowly get up and turn off the noise, already fed up...

* pleaseeeeeeeeeeeeeee

* THE CREDIT LARP IS NECESSARY

* i hold the keys

* RISE UP

* fix that?

* harry's suggestions xoxo

* runtime fix pt2

* You are the only thing that I still care about

* adds build workflow

* Update update_tgui.yml

* adds some needed steps

* ATM

* misc fixes and tweaks

* fixes 2

* make newscasters usable and fix use power on freezers

* turret control is clearer

---------

Co-authored-by: John Wildkins <john.wildkins@gmail.com>
Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: harryob <55142896+harryob@users.noreply.github.com>
Co-authored-by: Werner <Arrow768@users.noreply.github.com>
Co-authored-by: Geeves <ggrobler447@gmail.com>
Co-authored-by: harryob <me@harryob.live>
2023-06-25 19:03:33 +02:00

197 lines
5.0 KiB
JavaScript

/**
* @file
* @copyright 2020 Aleksej Komarov
* @license MIT
*/
/**
* Removes excess whitespace and indentation from the string.
*/
export const multiline = (str) => {
if (Array.isArray(str)) {
// Small stub to allow usage as a template tag
return multiline(str.join(''));
}
const lines = str.split('\n');
// Determine base indentation
let minIndent;
for (let line of lines) {
for (let indent = 0; indent < line.length; indent++) {
const char = line[indent];
if (char !== ' ') {
if (minIndent === undefined || indent < minIndent) {
minIndent = indent;
}
break;
}
}
}
if (!minIndent) {
minIndent = 0;
}
// Remove this base indentation and trim the resulting string
// from both ends.
return lines
.map((line) => line.substr(minIndent).trimRight())
.join('\n')
.trim();
};
/**
* Creates a glob pattern matcher.
*
* Matches strings with wildcards.
*
* Example: createGlobPattern('*@domain')('user@domain') === true
*/
export const createGlobPattern = (pattern) => {
const escapeString = (str) => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
// prettier-ignore
const regex = new RegExp('^'
+ pattern.split(/\*+/).map(escapeString).join('.*')
+ '$');
return (str) => regex.test(str);
};
/**
* Creates a search terms matcher.
*
* Returns true if given string matches the search text.
*
* @template T
* @param {string} searchText
* @param {(obj: T) => string} stringifier
* @returns {(obj: T) => boolean}
*/
export const createSearch = (searchText, stringifier) => {
const preparedSearchText = searchText.toLowerCase().trim();
return (obj) => {
if (!preparedSearchText) {
return true;
}
const str = stringifier ? stringifier(obj) : obj;
if (!str) {
return false;
}
return str.toLowerCase().includes(preparedSearchText);
};
};
/**
* Capitalizes a word and lowercases the rest.
* @param {string} str
* @returns {string} capitalized string
*
* @example capitalize('heLLo') === 'Hello'
*/
export const capitalize = (str) => {
// Handle array
if (Array.isArray(str)) {
return str.map(capitalize);
}
// Handle string
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
};
/**
* Similar to capitalize, this takes a string and replaces all first letters
* of any words.
*
* @param {string} str
* @return {string} The string with the first letters capitalized.
*
* @example capitalizeAll('heLLo woRLd') === 'HeLLo WoRLd'
*/
export const capitalizeAll = (str) => {
return str.replace(/(^\w{1})|(\s+\w{1})/g, (letter) => letter.toUpperCase());
};
/**
* Capitalizes only the first letter of the str.
*
* @param {string} str
* @return {string} capitalized string
*
* @example capitalizeFirst('heLLo woRLd') === 'HeLLo woRLd'
*/
export const capitalizeFirst = (str) => {
return str.replace(/^\w/, (letter) => letter.toUpperCase());
};
export const toTitleCase = (str) => {
// Handle array
if (Array.isArray(str)) {
return str.map(toTitleCase);
}
// Pass non-string
if (typeof str !== 'string') {
return str;
}
// Handle string
const WORDS_UPPER = ['Id', 'Tv'];
// prettier-ignore
const WORDS_LOWER = [
'A', 'An', 'And', 'As', 'At', 'But', 'By', 'For', 'For', 'From', 'In',
'Into', 'Near', 'Nor', 'Of', 'On', 'Onto', 'Or', 'The', 'To', 'With',
];
let currentStr = str.replace(/([^\W_]+[^\s-]*) */g, (str) => {
return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase();
});
for (let word of WORDS_LOWER) {
const regex = new RegExp('\\s' + word + '\\s', 'g');
currentStr = currentStr.replace(regex, (str) => str.toLowerCase());
}
for (let word of WORDS_UPPER) {
const regex = new RegExp('\\b' + word + '\\b', 'g');
currentStr = currentStr.replace(regex, (str) => str.toLowerCase());
}
return currentStr;
};
/**
* Decodes HTML entities, and removes unnecessary HTML tags.
*
* @param {String} str Encoded HTML string
* @return {String} Decoded HTML string
*/
export const decodeHtmlEntities = (str) => {
if (!str) {
return str;
}
const translate_re = /&(nbsp|amp|quot|lt|gt|apos);/g;
const translate = {
nbsp: ' ',
amp: '&',
quot: '"',
lt: '<',
gt: '>',
apos: "'",
};
// prettier-ignore
return str
// Newline tags
.replace(/<br>/gi, '\n')
.replace(/<\/?[a-z0-9-_]+[^>]*>/gi, '')
// Basic entities
.replace(translate_re, (match, entity) => translate[entity])
// Decimal entities
.replace(/&#?([0-9]+);/gi, (match, numStr) => {
const num = parseInt(numStr, 10);
return String.fromCharCode(num);
})
// Hex entities
.replace(/&#x?([0-9a-f]+);/gi, (match, numStr) => {
const num = parseInt(numStr, 16);
return String.fromCharCode(num);
});
};
/**
* Converts an object into a query string,
*/
// prettier-ignore
export const buildQueryString = obj => Object.keys(obj)
.map(key => encodeURIComponent(key)
+ '=' + encodeURIComponent(obj[key]))
.join('&');