Skip to main content

Overview

Proton WebClients provides a comprehensive set of utility functions for common operations like string manipulation, object transformations, DOM operations, and URL handling.

String Helpers

normalize

Normalize a string by converting to lowercase and optionally removing diacritics.
function normalize(
  value?: string,
  removeDiacritics?: boolean
): string
value
string
String to normalize
removeDiacritics
boolean
default:"false"
Whether to remove accents and diacritical marks
import { normalize } from '@proton/shared/lib/helpers/string';

const result = normalize('  Hello World  ');
// 'hello world'

truncateMore

Truncate a string with customizable start/end character display.
function truncateMore(options: {
  string: string;
  charsToDisplay?: number;
  charsToDisplayStart?: number;
  charsToDisplayEnd?: number;
  omission?: string;
  skewEnd?: boolean;
}): string
options.string
string
required
String to truncate
options.charsToDisplay
number
Total characters to display (truncates from middle)
options.charsToDisplayStart
number
default:"0"
Characters to show at start
options.charsToDisplayEnd
number
default:"0"
Characters to show at end
options.omission
string
default:"'…'"
String to use for truncation indicator
options.skewEnd
boolean
default:"false"
Skew truncation toward the end
import { truncateMore } from '@proton/shared/lib/helpers/string';

const result = truncateMore({
  string: 'verylongfilename.pdf',
  charsToDisplay: 15
});
// 'verylo…name.pdf'

getInitials

Get initials from a full name.
function getInitials(fullName?: string): string
import { getInitials } from '@proton/shared/lib/helpers/string';

getInitials('John Doe'); // 'JD'
getInitials('Alice'); // 'A'
getInitials(''); // '?'
getInitials('Jean-Pierre Martin'); // 'JM'

rtlSanitize

Remove RTL/LTR override unicode characters that can cause security issues.
function rtlSanitize(str: string): string
import { rtlSanitize } from '@proton/shared/lib/helpers/string';

// Protects against RTL override attacks
const safe = rtlSanitize(unsafeFilename);

Object Helpers

omit

Create a new object with specified properties removed.
function omit<T extends object, K extends keyof T>(
  model: T,
  properties?: readonly K[]
): Omit<T, K>
model
T
required
Source object
properties
readonly K[]
default:"[]"
Properties to omit
import { omit } from '@proton/shared/lib/helpers/object';

const user = {
  id: '1',
  name: 'John',
  password: 'secret',
  email: '[email protected]'
};

const publicUser = omit(user, ['password']);
// { id: '1', name: 'John', email: '[email protected]' }

pick

Create a new object with only specified properties.
function pick<T extends object, K extends keyof T>(
  model: T,
  properties?: readonly K[]
): Pick<T, K>
model
T
required
Source object
properties
readonly K[]
default:"[]"
Properties to keep
import { pick } from '@proton/shared/lib/helpers/object';

const user = {
  id: '1',
  name: 'John',
  email: '[email protected]',
  password: 'secret'
};

const publicData = pick(user, ['id', 'name', 'email']);
// { id: '1', name: 'John', email: '[email protected]' }

toMap

Convert an array to a map object keyed by a specific property.
function toMap<T extends { [key: string]: any }, K extends keyof T>(
  collection?: T[],
  key?: K
): { [key in T[K]]: T }
collection
T[]
default:"[]"
Array to convert
key
K
default:"'ID'"
Property to use as map key
import { toMap } from '@proton/shared/lib/helpers/object';

const users = [
  { ID: '1', name: 'John' },
  { ID: '2', name: 'Jane' },
  { ID: '3', name: 'Bob' }
];

const userMap = toMap(users);
// {
//   '1': { ID: '1', name: 'John' },
//   '2': { ID: '2', name: 'Jane' },
//   '3': { ID: '3', name: 'Bob' }
// }

toBitMap

Convert an object of boolean flags to a bitmap number.
function toBitMap(o?: { [key: string]: boolean }): number
import { toBitMap } from '@proton/shared/lib/helpers/object';

const flags = {
  announcements: true,
  features: false,
  newsletter: true,
  beta: false
};

const bitmap = toBitMap(flags);
// 5 (binary: 0101)

fromBitmap

Convert a bitmap number to an object of boolean flags.
function fromBitmap(
  value: number,
  keys?: string[]
): { [key: string]: boolean }
import { fromBitmap } from '@proton/shared/lib/helpers/object';

const flags = fromBitmap(5, [
  'announcements',
  'features',
  'newsletter',
  'beta'
]);
// {
//   announcements: true,
//   features: false,
//   newsletter: true,
//   beta: false
// }

DOM Helpers

loadScript

Dynamically load a JavaScript file.
function loadScript(
  path: string,
  integrity?: string
): Promise<Event>
path
string
required
URL of the script to load
integrity
string
Subresource Integrity (SRI) hash
import { loadScript } from '@proton/shared/lib/helpers/dom';

await loadScript(
  'https://cdn.example.com/library.js',
  'sha384-abc123...'
);

scrollIntoView

Safely scroll an element into view with cross-browser support.
function scrollIntoView(
  element: HTMLElement | undefined | null,
  extra?: boolean | ScrollIntoViewOptions
): void
import { scrollIntoView } from '@proton/shared/lib/helpers/dom';

const element = document.getElementById('target');
scrollIntoView(element, {
  behavior: 'smooth',
  block: 'nearest'
});

isElement

Check if a node is an Element node.
function isElement(node: Node | null): node is Element
import { isElement } from '@proton/shared/lib/helpers/dom';

const node = document.querySelector('.item');
if (isElement(node)) {
  // node is typed as Element
  node.classList.add('active');
}

getScrollParent

Find the nearest scrollable ancestor element.
function getScrollParent(
  element: HTMLElement | null | undefined,
  includeHidden?: boolean
): HTMLElement
element
HTMLElement | null | undefined
Element to start search from
includeHidden
boolean
default:"false"
Include elements with overflow: hidden
import { getScrollParent } from '@proton/shared/lib/helpers/dom';

const element = document.getElementById('nested');
const scrollContainer = getScrollParent(element);
scrollContainer.scrollTop = 0;

isVisible

Check if an element is visible (not hidden by CSS).
function isVisible(element: HTMLElement | null): boolean
import { isVisible } from '@proton/shared/lib/helpers/dom';

const element = document.querySelector('.modal');
if (isVisible(element)) {
  console.log('Modal is visible');
}

rootFontSize

Get the root font size in pixels.
function rootFontSize(reset?: boolean): number
reset
boolean
default:"false"
Force recalculation of cached value
import { rootFontSize } from '@proton/shared/lib/helpers/dom';

const remValue = 2; // 2rem
const pixels = remValue * rootFontSize();

URL Helpers

getSearchParams

Parse URL search parameters into an object.
function getSearchParams(search: string): ParsedSearchParams

type ParsedSearchParams = Partial<Record<string, string>>
import { getSearchParams } from '@proton/shared/lib/helpers/url';

const params = getSearchParams('?foo=bar&baz=qux');
// { foo: 'bar', baz: 'qux' }

stringifySearchParams

Convert an object to URL search parameters string.
function stringifySearchParams(
  params: { [key: string]: string | string[] | undefined | null },
  prefix?: string
): string
params
object
required
Parameters to stringify
prefix
string
Prefix to add (e.g., ’?‘)
import { stringifySearchParams } from '@proton/shared/lib/helpers/url';

const query = stringifySearchParams({
  search: 'hello',
  page: '2'
});
// 'search=hello&page=2'

changeSearchParams

Update URL search parameters.
function changeSearchParams(
  pathname: string,
  search: string,
  newParams?: ParsedSearchParams
): string
import { changeSearchParams } from '@proton/shared/lib/helpers/url';

const newUrl = changeSearchParams(
  '/app',
  '?page=1',
  { page: '2', filter: 'active' }
);
// '/app#page=2&filter=active'

getHostname

Extract hostname from a URL.
function getHostname(url?: string): string
import { getHostname } from '@proton/shared/lib/helpers/url';

const hostname = getHostname('https://mail.proton.me/inbox');
// 'mail.proton.me'

isValidHttpUrl

Check if a string is a valid HTTP(S) URL.
function isValidHttpUrl(string: string): boolean
import { isValidHttpUrl } from '@proton/shared/lib/helpers/url';

isValidHttpUrl('https://proton.me'); // true
isValidHttpUrl('ftp://example.com'); // false
isValidHttpUrl('not a url'); // false

joinPaths

Safely join URL path segments.
function joinPaths(...paths: string[]): string
import { joinPaths } from '@proton/shared/lib/helpers/url';

const url = joinPaths('/api/', '/users/', '/123/');
// '/api/users/123'

Best Practices

Import Only What You Need

// Good - tree-shakeable
import { normalize } from '@proton/shared/lib/helpers/string';

// Avoid - imports entire module
import * as stringHelpers from '@proton/shared/lib/helpers/string';

Type Safety

// Use type parameters for better type inference
const users = [{ ID: '1', name: 'John' }];
const userMap = toMap(users); // Fully typed

// Use type guards
if (isElement(node)) {
  // TypeScript knows node is Element here
  node.classList.add('active');
}

Performance

// Cache root font size
const rem = rootFontSize(); // Cached after first call

// Batch DOM operations
const elements = document.querySelectorAll('.item');
elements.forEach(el => {
  if (isVisible(el)) {
    // Process visible elements
  }
});

Build docs developers (and LLMs) love