1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-13 06:43:35 +00:00

Move to libs

This commit is contained in:
Hinton
2022-06-03 16:24:40 +02:00
parent 28d15bfe2a
commit d7492e3cf3
878 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
import { Pipe } from "@angular/core";
import { ColorPasswordPipe } from "./color-password.pipe";
/*
An updated pipe that extends ColourPasswordPipe to include a character count
*/
@Pipe({ name: "colorPasswordCount" })
export class ColorPasswordCountPipe extends ColorPasswordPipe {
transform(password: string) {
const template = (character: string, type: string, index: number) =>
`<span class="password-character password-${type}">
${character}<span class="password-count">${index + 1}</span>
</span>`;
const colorizedPasswordCount = this.generateTemplate(password, template);
return colorizedPasswordCount;
}
}

View File

@@ -0,0 +1,61 @@
import { Pipe, PipeTransform } from "@angular/core";
import { Utils } from "jslib-common/misc/utils";
/*
An updated pipe that sanitizes HTML, highlights numbers and special characters (in different colors each)
and handles Unicode / Emoji characters correctly.
*/
@Pipe({ name: "colorPassword" })
export class ColorPasswordPipe implements PipeTransform {
transform(password: string) {
const template = (character: string, type: string) =>
`<span class="password-${type}">${character}</span>`;
const colorizedPassword = this.generateTemplate(password, template);
return colorizedPassword;
}
protected generateTemplate(
password: string,
templateGenerator: (chararacter: string, type: string, index?: number) => string
) {
// Convert to an array to handle cases that stings have special characters, ie: emoji.
const passwordArray = Array.from(password);
let colorizedPassword = "";
for (let i = 0; i < passwordArray.length; i++) {
let character = passwordArray[i];
let isSpecial = false;
// Sanitize HTML first.
switch (character) {
case "&":
character = "&amp;";
isSpecial = true;
break;
case "<":
character = "&lt;";
isSpecial = true;
break;
case ">":
character = "&gt;";
isSpecial = true;
break;
case " ":
character = "&nbsp;";
isSpecial = true;
break;
default:
break;
}
let type = "letter";
if (character.match(Utils.regexpEmojiPresentation)) {
type = "emoji";
} else if (isSpecial || character.match(/[^\w ]/)) {
type = "special";
} else if (character.match(/\d/)) {
type = "number";
}
colorizedPassword += templateGenerator(character, type, i);
}
return colorizedPassword;
}
}

View File

@@ -0,0 +1,64 @@
import { Pipe, PipeTransform } from "@angular/core";
interface CardRuleEntry {
cardLength: number;
blocks: number[];
}
// See https://baymard.com/checkout-usability/credit-card-patterns for
// all possible credit card spacing patterns. For now, we just handle
// the below.
const numberFormats: Record<string, CardRuleEntry[]> = {
Visa: [{ cardLength: 16, blocks: [4, 4, 4, 4] }],
Mastercard: [{ cardLength: 16, blocks: [4, 4, 4, 4] }],
Maestro: [
{ cardLength: 16, blocks: [4, 4, 4, 4] },
{ cardLength: 13, blocks: [4, 4, 5] },
{ cardLength: 15, blocks: [4, 6, 5] },
{ cardLength: 19, blocks: [4, 4, 4, 4, 3] },
],
Discover: [{ cardLength: 16, blocks: [4, 4, 4, 4] }],
"Diners Club": [{ cardLength: 14, blocks: [4, 6, 4] }],
JCB: [{ cardLength: 16, blocks: [4, 4, 4, 4] }],
UnionPay: [
{ cardLength: 16, blocks: [4, 4, 4, 4] },
{ cardLength: 19, blocks: [6, 13] },
],
Amex: [{ cardLength: 15, blocks: [4, 6, 5] }],
Other: [{ cardLength: 16, blocks: [4, 4, 4, 4] }],
};
@Pipe({ name: "creditCardNumber" })
export class CreditCardNumberPipe implements PipeTransform {
transform(creditCardNumber: string, brand: string): string {
let rules = numberFormats[brand];
if (rules == null) {
rules = numberFormats["Other"];
}
const cardLength = creditCardNumber.length;
let matchingRule = rules.find((r) => r.cardLength == cardLength);
if (matchingRule == null) {
matchingRule = rules[0];
}
const blocks = matchingRule.blocks;
const chunks: string[] = [];
let total = 0;
blocks.forEach((c) => {
chunks.push(creditCardNumber.slice(total, total + c));
total += c;
});
// Append the remaining part
if (cardLength > total) {
chunks.push(creditCardNumber.slice(total));
}
return chunks.join(" ");
}
}

View File

@@ -0,0 +1,17 @@
import { Pipe, PipeTransform } from "@angular/core";
@Pipe({
name: "ellipsis",
})
export class EllipsisPipe implements PipeTransform {
transform(value: string, limit = 25, completeWords = false, ellipsis = "...") {
if (value.length <= limit) {
return value;
}
limit -= ellipsis.length;
if (completeWords && value.length > limit && value.indexOf(" ") > 0) {
limit = value.substring(0, limit).lastIndexOf(" ");
}
return value.substring(0, limit) + ellipsis;
}
}

View File

@@ -0,0 +1,14 @@
import { Pipe, PipeTransform } from "@angular/core";
import { I18nService } from "jslib-common/abstractions/i18n.service";
@Pipe({
name: "i18n",
})
export class I18nPipe implements PipeTransform {
constructor(private i18nService: I18nService) {}
transform(id: string, p1?: string, p2?: string, p3?: string): string {
return this.i18nService.t(id, p1, p2, p3);
}
}

View File

@@ -0,0 +1,41 @@
import { Pipe, PipeTransform } from "@angular/core";
import { CipherView } from "jslib-common/models/view/cipherView";
@Pipe({
name: "searchCiphers",
})
export class SearchCiphersPipe implements PipeTransform {
transform(ciphers: CipherView[], searchText: string, deleted = false): CipherView[] {
if (ciphers == null || ciphers.length === 0) {
return [];
}
if (searchText == null || searchText.length < 2) {
return ciphers.filter((c) => {
return deleted !== c.isDeleted;
});
}
searchText = searchText.trim().toLowerCase();
return ciphers.filter((c) => {
if (deleted !== c.isDeleted) {
return false;
}
if (c.name != null && c.name.toLowerCase().indexOf(searchText) > -1) {
return true;
}
if (searchText.length >= 8 && c.id.startsWith(searchText)) {
return true;
}
if (c.subTitle != null && c.subTitle.toLowerCase().indexOf(searchText) > -1) {
return true;
}
if (c.login && c.login.uri != null && c.login.uri.toLowerCase().indexOf(searchText) > -1) {
return true;
}
return false;
});
}
}

View File

@@ -0,0 +1,48 @@
import { Pipe, PipeTransform } from "@angular/core";
@Pipe({
name: "search",
})
export class SearchPipe implements PipeTransform {
transform(
items: any[],
searchText: string,
prop1?: string,
prop2?: string,
prop3?: string
): any[] {
if (items == null || items.length === 0) {
return [];
}
if (searchText == null || searchText.length < 2) {
return items;
}
searchText = searchText.trim().toLowerCase();
return items.filter((i) => {
if (
prop1 != null &&
i[prop1] != null &&
i[prop1].toString().toLowerCase().indexOf(searchText) > -1
) {
return true;
}
if (
prop2 != null &&
i[prop2] != null &&
i[prop2].toString().toLowerCase().indexOf(searchText) > -1
) {
return true;
}
if (
prop3 != null &&
i[prop3] != null &&
i[prop3].toString().toLowerCase().indexOf(searchText) > -1
) {
return true;
}
return false;
});
}
}

View File

@@ -0,0 +1,19 @@
import { Pipe, PipeTransform } from "@angular/core";
interface User {
name?: string;
email: string;
}
@Pipe({
name: "userName",
})
export class UserNamePipe implements PipeTransform {
transform(user?: User): string {
if (user == null) {
return null;
}
return user.name == null || user.name.trim() === "" ? user.email : user.name;
}
}