New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

expensify-common

Package Overview
Dependencies
Maintainers
1
Versions
120
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

expensify-common - npm Package Compare versions

Comparing version 2.0.18 to 2.0.19

200

dist/ExpensiMark.d.ts

@@ -1,100 +0,99 @@

import type Logger from './Logger';
declare type Replacement = (...args: string[], extras?: ExtrasObject) => string;
declare type Name =
| 'codeFence'
| 'inlineCodeBlock'
| 'email'
| 'link'
| 'hereMentions'
| 'userMentions'
| 'reportMentions'
| 'autoEmail'
| 'autolink'
| 'quote'
| 'italic'
| 'bold'
| 'strikethrough'
| 'heading1'
| 'newline'
| 'replacepre'
| 'listItem'
| 'exclude'
| 'anchor'
| 'breakline'
| 'blockquoteWrapHeadingOpen'
| 'blockquoteWrapHeadingClose'
| 'blockElementOpen'
| 'blockElementClose'
| 'stripTag';
declare type Rule = {
name: Name;
process?: (textToProcess: string, replacement: Replacement) => string;
regex?: RegExp;
replacement: Replacement | string;
pre?: (input: string) => string;
post?: (input: string) => string;
};
declare type ExtrasObject = {
import Logger from './Logger';
type Extras = {
reportIDToName?: Record<string, string>;
accountIDToName?: Record<string, string>;
cacheVideoAttributes?: (vidSource: string, attrs: string) => void;
};
declare type ExtraParamsForReplaceFunc = {
videoAttributeCache?: Record<string, string>;
};
type ReplacementFn = (extras: Extras, ...matches: string[]) => string;
type Replacement = ReplacementFn | string;
type ProcessFn = (textToProcess: string, replacement: Replacement, shouldKeepRawInput: boolean) => string;
type CommonRule = {
name: string;
replacement: Replacement;
rawInputReplacement?: Replacement;
pre?: (input: string) => string;
post?: (input: string) => string;
};
type RuleWithRegex = CommonRule & {
regex: RegExp;
};
type RuleWithProcess = CommonRule & {
process: ProcessFn;
};
type Rule = RuleWithRegex | RuleWithProcess;
type ReplaceOptions = {
extras?: Extras;
filterRules?: string[];
disabledRules?: string[];
shouldEscapeText?: boolean;
shouldKeepRawInput?: boolean;
};
export default class ExpensiMark {
static Log: Logger;
/**
* Set the logger to use for logging inside of the ExpensiMark class
* @param logger - The logger object to use
*/
static setLogger(logger: Logger): void;
/** Rules to apply to the text */
rules: Rule[];
htmlToMarkdownRules: Rule[];
htmlToTextRules: Rule[];
/**
* The list of regex replacements to do on a HTML comment for converting it to markdown.
* Order of rules is important
*/
htmlToMarkdownRules: RuleWithRegex[];
/**
* The list of rules to covert the HTML to text.
* Order of rules is important
*/
htmlToTextRules: RuleWithRegex[];
/**
* The list of rules that we have to exclude in shouldKeepWhitespaceRules list.
*/
whitespaceRulesToDisable: string[];
/**
* The list of rules that have to be applied when shouldKeepWhitespace flag is true.
*/
filterRules: (rule: Rule) => boolean;
/**
* Filters rules to determine which should keep whitespace.
*/
shouldKeepWhitespaceRules: Rule[];
/**
* maxQuoteDepth is the maximum depth of nested quotes that we want to support.
*/
maxQuoteDepth: number;
/**
* currentQuoteDepth is the current depth of nested quotes that we are processing.
*/
currentQuoteDepth: number;
constructor();
/**
* Retrieves the HTML ruleset based on the provided filter rules, disabled rules, and shouldKeepRawInput flag.
* @param filterRules - An array of rule names to filter the ruleset.
* @param disabledRules - An array of rule names to disable in the ruleset.
* @param shouldKeepRawInput - A boolean flag indicating whether to keep raw input.
*/
getHtmlRuleset(filterRules: string[], disabledRules: string[], shouldKeepRawInput: boolean): Rule[];
/**
* Replaces markdown with html elements
*
* @param text - Text to parse as markdown
* @param options - Options to customize the markdown parser
* @param options.filterRules=[] - An array of name of rules as defined in this class.
* If not provided, all available rules will be applied. If provided, only the rules in the array will be applied.
* @param options.disabledRules=[] - An array of name of rules as defined in this class.
* @param [options] - Options to customize the markdown parser
* @param [options.filterRules=[]] - An array of name of rules as defined in this class.
* If not provided, all available rules will be applied.
* @param [options.shouldEscapeText=true] - Whether or not the text should be escaped
* @param [options.disabledRules=[]] - An array of name of rules as defined in this class.
* If not provided, all available rules will be applied. If provided, the rules in the array will be skipped.
* @param options.shouldEscapeText=true - Whether or not the text should be escaped
* @param options.shouldKeepRawInput=false - Whether or not the raw input should be kept and returned
*/
replace(
text: string,
{
filterRules,
shouldEscapeText,
shouldKeepRawInput,
extras,
}?: {
filterRules?: Name[];
disabledRules?: Name[];
shouldEscapeText?: boolean;
shouldKeepRawInput?: boolean;
extras?: ExtraParamsForReplaceFunc;
},
): string;
replace(text: string, { filterRules, shouldEscapeText, shouldKeepRawInput, disabledRules, extras }?: ReplaceOptions): string;
/**
* Checks matched URLs for validity and replace valid links with html elements
*
* @param regex
* @param textToCheck
* @param replacement
*/
modifyTextForUrlLinks(regex: RegExp, textToCheck: string, replacement: Replacement): string;
modifyTextForUrlLinks(regex: RegExp, textToCheck: string, replacement: ReplacementFn): string;
/**
* Checks matched Emails for validity and replace valid links with html elements
*
* @param regex
* @param textToCheck
* @param replacement
*/
modifyTextForEmailLinks(regex: RegExp, textToCheck: string, replacement: Replacement): string;
modifyTextForEmailLinks(regex: RegExp, textToCheck: string, replacement: ReplacementFn, shouldKeepRawInput: boolean): string;
/**

@@ -106,4 +105,2 @@ * replace block element with '\n' if :

* 4. It's not the last element in the string.
*
* @param htmlString
*/

@@ -113,45 +110,44 @@ replaceBlockElementWithNewLine(htmlString: string): string;

* Replaces HTML with markdown
*
* @param htmlString
* @param extras
*/
htmlToMarkdown(htmlString: string, extras?: ExtrasObject): string;
htmlToMarkdown(htmlString: string, extras?: Extras): string;
/**
* Convert HTML to text
*
* @param htmlString
* @param extras
*/
htmlToText(htmlString: string, extras?: ExtrasObject): string;
htmlToText(htmlString: string, extras?: Extras): string;
/**
* Modify text for Quotes replacing chevrons with html elements
*
* @param regex
* @param textToCheck
* @param replacement
*/
modifyTextForQuote(regex: RegExp, textToCheck: string, replacement: Replacement): string;
modifyTextForQuote(regex: RegExp, textToCheck: string, replacement: ReplacementFn): string;
/**
* Format the content of blockquote if the text matches the regex or else just return the original text
*
* @param regex
* @param textToCheck
* @param replacement
*/
formatTextForQuote(regex: RegExp, textToCheck: string, replacement: Replacement): string;
formatTextForQuote(regex: RegExp, textToCheck: string, replacement: ReplacementFn): string;
/**
* Check if the input text includes only the open or the close tag of an element.
*
* @param textToCheck - Text to check
*/
containsNonPairTag(textToCheck: string): boolean;
/**
* @returns array or undefined if exception occurs when executing regex matching
*/
extractLinksInMarkdownComment(comment: string): string[] | undefined;
/**
* Compares two markdown comments and returns a list of the links removed in a new comment.
*
* @param oldComment
* @param newComment
*/
getRemovedMarkdownLinks(oldComment: string, newComment: string): string[];
/**
* Escapes the content of an HTML attribute value
* @param content - string content that possible contains HTML
* @returns original MD content escaped for use in HTML attribute value
*/
escapeAttributeContent(content: string): string;
/**
* Replaces text with a replacement based on a regex
* @param text - The text to replace
* @param regexp - The regex to match
* @param extras - The extras object
* @param replacement - The replacement string or function
* @returns The replaced text
*/
replaceTextWithExtras(text: string, regexp: RegExp, extras: Extras, replacement: Replacement): string;
}
export {};

@@ -34,2 +34,3 @@ "use strict";

const Utils = __importStar(require("./utils"));
const EXTRAS_DEFAULT = {};
const MARKDOWN_LINK_REGEX = new RegExp(`\\[([^\\][]*(?:\\[[^\\][]*][^\\][]*)*)]\\(${UrlPatterns.MARKDOWN_URL_REGEX}\\)(?![^<]*(<\\/pre>|<\\/code>))`, 'gi');

@@ -42,3 +43,3 @@ const MARKDOWN_IMAGE_REGEX = new RegExp(`\\!(?:\\[([^\\][]*(?:\\[[^\\][]*][^\\][]*)*)])?\\(${UrlPatterns.MARKDOWN_URL_REGEX}\\)(?![^<]*(<\\/pre>|<\\/code>))`, 'gi');

* Set the logger to use for logging inside of the ExpensiMark class
* @param {Object} logger - The logger object to use
* @param logger - The logger object to use
*/

@@ -50,6 +51,8 @@ static setLogger(logger) {

/**
* The list of rules that we have to exclude in shouldKeepWhitespaceRules list.
*/
this.whitespaceRulesToDisable = ['newline', 'replacepre', 'replacebr', 'replaceh1br'];
/**
* The list of regex replacements to do on a comment. Check the link regex is first so links are processed
* before other delimiters
*
* @type {Object[]}
*/

@@ -61,3 +64,3 @@ this.rules = [

regex: Constants.CONST.REG_EXP.EMOJI_RULE,
replacement: (match) => `<emoji>${match}</emoji>`,
replacement: (_extras, match) => `<emoji>${match}</emoji>`,
},

@@ -78,7 +81,7 @@ /**

// &nbsp; will create styling issues so use &#32;
replacement: (match, __, textWithinFences) => {
replacement: (_extras, _match, _g1, textWithinFences) => {
const group = textWithinFences.replace(/(?:(?![\n\r])\s)/g, '&#32;');
return `<pre>${group}</pre>`;
},
rawInputReplacement: (match, __, textWithinFences) => {
rawInputReplacement: (_extras, _match, _g1, textWithinFences) => {
const group = textWithinFences.replace(/(?:(?![\n\r])\s)/g, '&#32;').replace(/<emoji>|<\/emoji>/g, '');

@@ -111,3 +114,3 @@ return `<pre>${group}</pre>`;

},
replacement: (match, g1, g2) => {
replacement: (_extras, match, g1, g2) => {
if (g1.match(Constants.CONST.REG_EXP.EMOJIS) || !g1.trim()) {

@@ -121,3 +124,3 @@ return match;

},
rawInputReplacement: (match, g1, g2, g3) => {
rawInputReplacement: (_extras, match, g1, g2, g3) => {
if (g1.match(Constants.CONST.REG_EXP.EMOJIS) || !g1.trim()) {

@@ -135,3 +138,3 @@ return match;

const regexp = shouldKeepRawInput ? /^# ( *(?! )(?:(?!<pre>|\n|\r\n).)+)/gm : /^# +(?! )((?:(?!<pre>|\n|\r\n).)+)/gm;
return textToProcess.replace(regexp, replacement);
return this.replaceTextWithExtras(textToProcess, regexp, EXTRAS_DEFAULT, replacement);
},

@@ -149,15 +152,12 @@ replacement: '<h1>$1</h1>',

/**
* @param {string} match
* @param {string} videoName - The first capture group - video name
* @param {string} videoSource - The second capture group - video URL
* @param {any[]} args - The rest capture groups and `extras` object. args[args.length-1] will the `extras` object
* @return {string} Returns the HTML video tag
* @param extras - The extras object
* @param videoName - The first capture group - video name
* @param videoSource - The second capture group - video URL
* @return Returns the HTML video tag
*/
replacement: (match, videoName, videoSource, ...args) => {
const extras = args[args.length - 1];
replacement: (extras, _match, videoName, videoSource) => {
const extraAttrs = extras && extras.videoAttributeCache && extras.videoAttributeCache[videoSource];
return `<video data-expensify-source="${str_1.default.sanitizeURL(videoSource)}" ${extraAttrs || ''}>${videoName ? `${videoName}` : ''}</video>`;
},
rawInputReplacement: (match, videoName, videoSource, ...args) => {
const extras = args[args.length - 1];
rawInputReplacement: (extras, _match, videoName, videoSource) => {
const extraAttrs = extras && extras.videoAttributeCache && extras.videoAttributeCache[videoSource];

@@ -177,4 +177,4 @@ return `<video data-expensify-source="${str_1.default.sanitizeURL(videoSource)}" data-raw-href="${videoSource}" data-link-variant="${typeof videoName === 'string' ? 'labeled' : 'auto'}" ${extraAttrs || ''}>${videoName ? `${videoName}` : ''}</video>`;

regex: MARKDOWN_IMAGE_REGEX,
replacement: (match, g1, g2) => `<img src="${str_1.default.sanitizeURL(g2)}"${g1 ? ` alt="${this.escapeAttributeContent(g1)}"` : ''} />`,
rawInputReplacement: (match, g1, g2) => `<img src="${str_1.default.sanitizeURL(g2)}"${g1 ? ` alt="${this.escapeAttributeContent(g1)}"` : ''} data-raw-href="${g2}" data-link-variant="${typeof g1 === 'string' ? 'labeled' : 'auto'}" />`,
replacement: (_extras, _match, g1, g2) => `<img src="${str_1.default.sanitizeURL(g2)}"${g1 ? ` alt="${this.escapeAttributeContent(g1)}"` : ''} />`,
rawInputReplacement: (_extras, _match, g1, g2) => `<img src="${str_1.default.sanitizeURL(g2)}"${g1 ? ` alt="${this.escapeAttributeContent(g1)}"` : ''} data-raw-href="${g2}" data-link-variant="${typeof g1 === 'string' ? 'labeled' : 'auto'}" />`,
},

@@ -189,3 +189,3 @@ /**

process: (textToProcess, replacement) => this.modifyTextForUrlLinks(MARKDOWN_LINK_REGEX, textToProcess, replacement),
replacement: (match, g1, g2) => {
replacement: (_extras, match, g1, g2) => {
if (g1.match(Constants.CONST.REG_EXP.EMOJIS) || !g1.trim()) {

@@ -196,3 +196,3 @@ return match;

},
rawInputReplacement: (match, g1, g2) => {
rawInputReplacement: (_extras, match, g1, g2) => {
if (g1.match(Constants.CONST.REG_EXP.EMOJIS) || !g1.trim()) {

@@ -214,3 +214,3 @@ return match;

regex: /([a-zA-Z0-9.!$%&+/=?^`{|}_-]?)(@here)([.!$%&+/=?^`{|}_-]?)(?=\b)(?!([\w'#%+-]*@(?:[a-z\d-]+\.)+[a-z]{2,}(?:\s|$|@here))|((?:(?!<a).)+)?<\/a>|[^<]*(<\/pre>|<\/code>))/gm,
replacement: (match, g1, g2, g3) => {
replacement: (_extras, match, g1, g2, g3) => {
if (!str_1.default.isValidMention(match)) {

@@ -245,3 +245,3 @@ return match;

regex: new RegExp(`(@here|[a-zA-Z0-9.!$%&+=?^\`{|}-]?)(@${Constants.CONST.REG_EXP.EMAIL_PART}|@${Constants.CONST.REG_EXP.PHONE_PART})(?!((?:(?!<a).)+)?<\\/a>|[^<]*(<\\/pre>|<\\/code>))`, 'gim'),
replacement: (match, g1, g2) => {
replacement: (_extras, match, g1, g2) => {
const phoneNumberRegex = new RegExp(`^${Constants.CONST.REG_EXP.PHONE_PART}$`);

@@ -256,3 +256,3 @@ const mention = g2.slice(1);

},
rawInputReplacement: (match, g1, g2) => {
rawInputReplacement: (_extras, match, g1, g2) => {
const phoneNumberRegex = new RegExp(`^${Constants.CONST.REG_EXP.PHONE_PART}$`);

@@ -282,7 +282,7 @@ const mention = g2.slice(1);

},
replacement: (match, g1, g2) => {
replacement: (_extras, _match, g1, g2) => {
const href = str_1.default.sanitizeURL(g2);
return `${g1}<a href="${href}" target="_blank" rel="noreferrer noopener">${g2}</a>${g1}`;
},
rawInputReplacement: (_match, g1, g2) => {
rawInputReplacement: (_extras, _match, g1, g2) => {
const href = str_1.default.sanitizeURL(g2);

@@ -299,19 +299,34 @@ return `${g1}<a href="${href}" data-raw-href="${g2}" data-link-variant="auto" target="_blank" rel="noreferrer noopener">${g2}</a>${g1}`;

const regex = /^(?:&gt;)+ +(?! )(?![^<]*(?:<\/pre>|<\/code>))([^\v\n\r]+)/gm;
const replaceFunction = (g1) => replacement(g1, shouldKeepRawInput);
if (shouldKeepRawInput) {
const rawInputRegex = /^(?:&gt;)+ +(?! )(?![^<]*(?:<\/pre>|<\/code>))([^\v\n\r]*)/gm;
return textToProcess.replace(rawInputRegex, replaceFunction);
return this.replaceTextWithExtras(textToProcess, rawInputRegex, EXTRAS_DEFAULT, replacement);
}
return this.modifyTextForQuote(regex, textToProcess, replacement);
},
replacement: (g1, shouldKeepRawInput = false) => {
replacement: (_extras, g1) => {
// We want to enable 2 options of nested heading inside the blockquote: "># heading" and "> # heading".
// To do this we need to parse body of the quote without first space
const handleMatch = (match) => match;
const textToReplace = g1.replace(/^&gt;( )?/gm, handleMatch);
const filterRules = ['heading1'];
// if we don't reach the max quote depth we allow the recursive call to process possible quote
if (this.currentQuoteDepth < this.maxQuoteDepth - 1) {
filterRules.push('quote');
this.currentQuoteDepth++;
}
const replacedText = this.replace(textToReplace, {
filterRules,
shouldEscapeText: false,
shouldKeepRawInput: false,
});
this.currentQuoteDepth = 0;
return `<blockquote>${replacedText}</blockquote>`;
},
rawInputReplacement: (_extras, g1) => {
// We want to enable 2 options of nested heading inside the blockquote: "># heading" and "> # heading".
// To do this we need to parse body of the quote without first space
let isStartingWithSpace = false;
const handleMatch = (match, g2) => {
if (shouldKeepRawInput) {
isStartingWithSpace = !!g2;
return '';
}
return match;
const handleMatch = (_match, g2) => {
isStartingWithSpace = !!g2;
return '';
};

@@ -328,3 +343,3 @@ const textToReplace = g1.replace(/^&gt;( )?/gm, handleMatch);

shouldEscapeText: false,
shouldKeepRawInput,
shouldKeepRawInput: true,
});

@@ -343,3 +358,3 @@ this.currentQuoteDepth = 0;

regex: /(<(pre|code|a|mention-user)[^>]*>(.*?)<\/\2>)|((\b_+|\b)_((?![\s_])[\s\S]*?[^\s_](?<!\s))_(?![^\W_])(?![^<]*>)(?![^<]*(<\/pre>|<\/code>|<\/a>|<\/mention-user>)))/g,
replacement: (match, html, tag, content, text, extraLeadingUnderscores, textWithinUnderscores) => {
replacement: (_extras, match, html, tag, content, text, extraLeadingUnderscores, textWithinUnderscores) => {
// Skip any <pre>, <code>, <a>, <mention-user> tag contents

@@ -376,3 +391,3 @@ if (html) {

regex: /(?<!<[^>]*)\B\*(?![^<]*(?:<\/pre>|<\/code>|<\/a>))((?![\s*])[\s\S]*?[^\s*](?<!\s))\*\B(?![^<]*>)(?![^<]*(<\/pre>|<\/code>|<\/a>))/g,
replacement: (match, g1) => (g1.includes('</pre>') || this.containsNonPairTag(g1) ? match : `<strong>${g1}</strong>`),
replacement: (_extras, match, g1) => (g1.includes('</pre>') || this.containsNonPairTag(g1) ? match : `<strong>${g1}</strong>`),
},

@@ -382,3 +397,3 @@ {

regex: /(?<!<[^>]*)\B~((?![\s~])[\s\S]*?[^\s~](?<!\s))~\B(?![^<]*>)(?![^<]*(<\/pre>|<\/code>|<\/a>))/g,
replacement: (match, g1) => (g1.includes('</pre>') || this.containsNonPairTag(g1) ? match : `<del>${g1}</del>`),
replacement: (_extras, match, g1) => (g1.includes('</pre>') || this.containsNonPairTag(g1) ? match : `<del>${g1}</del>`),
},

@@ -406,3 +421,2 @@ {

* Order of rules is important
* @type {Object[]}
*/

@@ -470,3 +484,3 @@ this.htmlToMarkdownRules = [

regex: /<(blockquote|q)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi,
replacement: (match, g1, g2) => {
replacement: (_extras, _match, _g1, g2) => {
// We remove the line break before heading inside quote to avoid adding extra line

@@ -506,3 +520,3 @@ let resultString = g2

regex: /<(pre)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)(\n?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi,
replacement: (match, g1, g2) => `\`\`\`\n${g2}\n\`\`\``,
replacement: (_extras, _match, _g1, g2) => `\`\`\`\n${g2}\n\`\`\``,
},

@@ -512,3 +526,3 @@ {

regex: /<(a)[^><]*href\s*=\s*(['"])(.*?)\2(?:".*?"|'.*?'|[^'"><])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi,
replacement: (match, g1, g2, g3, g4) => {
replacement: (_extras, _match, _g1, _g2, g3, g4) => {
const email = g3.startsWith('mailto:') ? g3.slice(7) : '';

@@ -524,3 +538,3 @@ if (email === g4) {

regex: /<img[^><]*src\s*=\s*(['"])(.*?)\1(?:[^><]*alt\s*=\s*(['"])(.*?)\3)?[^><]*>*(?![^<][\s\S]*?(<\/pre>|<\/code>))/gi,
replacement: (match, g1, g2, g3, g4) => {
replacement: (_extras, _match, _g1, g2, _g3, g4) => {
if (g4) {

@@ -536,12 +550,11 @@ return `![${g4}](${g2})`;

/**
* @param {string} match The full match
* @param {string} g1 {string} The first capture group
* @param {string} videoSource - the second capture group - video source (video URL)
* @param {string} videoAttrs - the third capture group - video attributes (data-expensify-width, data-expensify-height, etc...)
* @param {string} videoName - the fourth capture group will be the video file name (the text between opening and closing video tags)
* @param {any[]} args The rest of the arguments. args[args.length-1] will the `extras` object
* @returns {string} Returns the markdown video tag
* @param extras - The extras object
* @param match The full match
* @param _g1 The first capture group
* @param videoSource - the second capture group - video source (video URL)
* @param videoAttrs - the third capture group - video attributes (data-expensify-width, data-expensify-height, etc...)
* @param videoName - the fourth capture group will be the video file name (the text between opening and closing video tags)
* @returns The markdown video tag
*/
replacement: (match, g1, videoSource, videoAttrs, videoName, ...args) => {
const extras = args[args.length - 1];
replacement: (extras, _match, _g1, videoSource, videoAttrs, videoName) => {
if (videoAttrs && extras && extras.cacheVideoAttributes && typeof extras.cacheVideoAttributes === 'function') {

@@ -559,3 +572,3 @@ extras.cacheVideoAttributes(videoSource, videoAttrs);

regex: /<mention-report reportID="(\d+)" *\/>/gi,
replacement: (match, g1, offset, string, extras) => {
replacement: (extras, _match, g1, _offset, _string) => {
const reportToNameMap = extras.reportIDToName;

@@ -572,3 +585,4 @@ if (!reportToNameMap || !reportToNameMap[g1]) {

regex: /(?:<mention-user accountID="(\d+)" *\/>)|(?:<mention-user>(.*?)<\/mention-user>)/gi,
replacement: (match, g1, g2, offset, string, extras) => {
replacement: (extras, _match, g1, g2, _offset, _string) => {
var _a;
if (g1) {

@@ -580,3 +594,3 @@ const accountToNameMap = extras.accountIDToName;

}
return `@${extras.accountIDToName[g1]}`;
return `@${(_a = extras.accountIDToName) === null || _a === void 0 ? void 0 : _a[g1]}`;
}

@@ -590,3 +604,2 @@ return str_1.default.removeSMSDomain(g2);

* Order of rules is important
* @type {Object[]}
*/

@@ -632,3 +645,3 @@ this.htmlToTextRules = [

regex: /<mention-report reportID="(\d+)" *\/>/gi,
replacement: (match, g1, offset, string, extras) => {
replacement: (extras, _match, g1, _offset, _string) => {
const reportToNameMap = extras.reportIDToName;

@@ -645,3 +658,4 @@ if (!reportToNameMap || !reportToNameMap[g1]) {

regex: /<mention-user accountID="(\d+)" *\/>/gi,
replacement: (match, g1, offset, string, extras) => {
replacement: (extras, _match, g1, _offset, _string) => {
var _a;
const accountToNameMap = extras.accountIDToName;

@@ -652,3 +666,3 @@ if (!accountToNameMap || !accountToNameMap[g1]) {

}
return `@${extras.accountIDToName[g1]}`;
return `@${(_a = extras.accountIDToName) === null || _a === void 0 ? void 0 : _a[g1]}`;
},

@@ -664,3 +678,2 @@ },

* The list of rules that we have to exclude in shouldKeepWhitespaceRules list.
* @type {Object[]}
*/

@@ -670,4 +683,4 @@ this.whitespaceRulesToDisable = ['newline', 'replacepre', 'replacebr', 'replaceh1br'];

* The list of rules that have to be applied when shouldKeepWhitespace flag is true.
* @param {Object} rule - The rule to check.
* @returns {boolean} Returns true if the rule should be applied, otherwise false.
* @param rule - The rule to check.
* @returns true if the rule should be applied, otherwise false.
*/

@@ -677,3 +690,3 @@ this.filterRules = (rule) => !this.whitespaceRulesToDisable.includes(rule.name);

* Filters rules to determine which should keep whitespace.
* @returns {Object[]} The filtered rules.
* @returns The filtered rules.
*/

@@ -683,3 +696,2 @@ this.shouldKeepWhitespaceRules = this.rules.filter(this.filterRules);

* maxQuoteDepth is the maximum depth of nested quotes that we want to support.
* @type {Number}
*/

@@ -689,6 +701,11 @@ this.maxQuoteDepth = 3;

* currentQuoteDepth is the current depth of nested quotes that we are processing.
* @type {Number}
*/
this.currentQuoteDepth = 0;
}
/**
* Retrieves the HTML ruleset based on the provided filter rules, disabled rules, and shouldKeepRawInput flag.
* @param filterRules - An array of rule names to filter the ruleset.
* @param disabledRules - An array of rule names to disable in the ruleset.
* @param shouldKeepRawInput - A boolean flag indicating whether to keep raw input.
*/
getHtmlRuleset(filterRules, disabledRules, shouldKeepRawInput) {

@@ -712,13 +729,11 @@ let rules = this.rules;

*
* @param {String} text - Text to parse as markdown
* @param {Object} [options] - Options to customize the markdown parser
* @param {String[]} [options.filterRules=[]] - An array of name of rules as defined in this class.
* @param text - Text to parse as markdown
* @param [options] - Options to customize the markdown parser
* @param [options.filterRules=[]] - An array of name of rules as defined in this class.
* If not provided, all available rules will be applied.
* @param {Boolean} [options.shouldEscapeText=true] - Whether or not the text should be escaped
* @param {String[]} [options.disabledRules=[]] - An array of name of rules as defined in this class.
* @param [options.shouldEscapeText=true] - Whether or not the text should be escaped
* @param [options.disabledRules=[]] - An array of name of rules as defined in this class.
* If not provided, all available rules will be applied. If provided, the rules in the array will be skipped.
*
* @returns {String}
*/
replace(text, { filterRules = [], shouldEscapeText = true, shouldKeepRawInput = false, disabledRules = [], extras } = {}) {
replace(text, { filterRules = [], shouldEscapeText = true, shouldKeepRawInput = false, disabledRules = [], extras = EXTRAS_DEFAULT } = {}) {
// This ensures that any html the user puts into the comment field shows as raw html

@@ -732,9 +747,8 @@ let replacedText = shouldEscapeText ? Utils.escape(text) : text;

}
const replacementFunction = shouldKeepRawInput && rule.rawInputReplacement ? rule.rawInputReplacement : rule.replacement;
const replacementFnWithExtraParams = typeof replacementFunction === 'function' ? (...args) => replacementFunction(...args, extras) : replacementFunction;
if (rule.process) {
replacedText = rule.process(replacedText, replacementFnWithExtraParams, shouldKeepRawInput);
const replacement = shouldKeepRawInput && rule.rawInputReplacement ? rule.rawInputReplacement : rule.replacement;
if ('process' in rule) {
replacedText = rule.process(replacedText, replacement, shouldKeepRawInput);
}
else {
replacedText = replacedText.replace(rule.regex, replacementFnWithExtraParams);
replacedText = this.replaceTextWithExtras(replacedText, rule.regex, extras, replacement);
}

@@ -750,4 +764,3 @@ // Post-process text after applying regex

catch (e) {
// eslint-disable-next-line no-console
console.warn('Error replacing text with html in ExpensiMark.replace', { error: e });
ExpensiMark.Log.alert('Error replacing text with html in ExpensiMark.replace', { error: e });
// We want to return text without applying rules if exception occurs during replacing

@@ -760,8 +773,2 @@ return shouldEscapeText ? Utils.escape(text) : text;

* Checks matched URLs for validity and replace valid links with html elements
*
* @param {RegExp} regex
* @param {String} textToCheck
* @param {Function} replacement
*
* @returns {String}
*/

@@ -849,3 +856,3 @@ modifyTextForUrlLinks(regex, textToCheck, replacement) {

});
replacedText = replacedText.concat(replacement(match[0], linkText, url));
replacedText = replacedText.concat(replacement(EXTRAS_DEFAULT, match[0], linkText, url));
}

@@ -863,9 +870,2 @@ startIndex = match.index + match[0].length;

* Checks matched Emails for validity and replace valid links with html elements
*
* @param {RegExp} regex
* @param {String} textToCheck
* @param {Function} replacement
* @param {Boolean} shouldKeepRawInput
*
* @returns {String}
*/

@@ -884,4 +884,4 @@ modifyTextForEmailLinks(regex, textToCheck, replacement, shouldKeepRawInput) {

});
// rawInputReplacment needs to be called with additional parameters from match
const replacedMatch = shouldKeepRawInput ? replacement(match[0], linkText, match[2], match[3]) : replacement(match[0], linkText, match[3]);
// rawInputReplacement needs to be called with additional parameters from match
const replacedMatch = shouldKeepRawInput ? replacement(EXTRAS_DEFAULT, match[0], linkText, match[2], match[3]) : replacement(EXTRAS_DEFAULT, match[0], linkText, match[3]);
replacedText = replacedText.concat(replacedMatch);

@@ -903,5 +903,2 @@ startIndex = match.index + match[0].length;

* 4. It's not the last element in the string.
*
* @param {String} htmlString
* @returns {String}
*/

@@ -938,9 +935,4 @@ replaceBlockElementWithNewLine(htmlString) {

* Replaces HTML with markdown
*
* @param {String} htmlString
* @param {Object} extras
*
* @returns {String}
*/
htmlToMarkdown(htmlString, extras = {}) {
htmlToMarkdown(htmlString, extras = EXTRAS_DEFAULT) {
let generatedMarkdown = htmlString;

@@ -958,5 +950,3 @@ const body = /<(body)(?:"[^"]*"|'[^']*'|[^'"><])*>(?:\n|\r\n)?([\s\S]*?)(?:\n|\r\n)?<\/\1>(?![^<]*(<\/pre>|<\/code>))/im;

}
// if replacement is a function, we want to pass optional extras to it
const replacementFunction = Utils.isFunction(rule.replacement) ? (...args) => rule.replacement(...args, extras) : rule.replacement;
generatedMarkdown = generatedMarkdown.replace(rule.regex, replacementFunction);
generatedMarkdown = this.replaceTextWithExtras(generatedMarkdown, rule.regex, extras, rule.replacement);
};

@@ -968,14 +958,7 @@ this.htmlToMarkdownRules.forEach(processRule);

* Convert HTML to text
*
* @param {String} htmlString
* @param {Object} extras
*
* @returns {String}
*/
htmlToText(htmlString, extras = {}) {
htmlToText(htmlString, extras = EXTRAS_DEFAULT) {
let replacedText = htmlString;
const processRule = (rule) => {
// if replacement is a function, we want to pass optional extras to it
const replacementFunction = Utils.isFunction(rule.replacement) ? (...args) => rule.replacement(...args, extras) : rule.replacement;
replacedText = replacedText.replace(rule.regex, replacementFunction);
replacedText = this.replaceTextWithExtras(replacedText, rule.regex, extras, rule.replacement);
};

@@ -990,8 +973,2 @@ this.htmlToTextRules.forEach(processRule);

* Modify text for Quotes replacing chevrons with html elements
*
* @param {RegExp} regex
* @param {String} textToCheck
* @param {Function} replacement
*
* @returns {String}
*/

@@ -1048,8 +1025,2 @@ modifyTextForQuote(regex, textToCheck, replacement) {

* Format the content of blockquote if the text matches the regex or else just return the original text
*
* @param {RegExp} regex
* @param {String} textToCheck
* @param {Function} replacement
*
* @returns {String}
*/

@@ -1069,3 +1040,3 @@ formatTextForQuote(regex, textToCheck, replacement) {

textToFormat = textToFormat.replace(/^\n+|\n+$/g, '');
return replacement(textToFormat);
return replacement(EXTRAS_DEFAULT, textToFormat);
}

@@ -1076,6 +1047,2 @@ return textToCheck;

* Check if the input text includes only the open or the close tag of an element.
*
* @param {String} textToCheck - Text to check
*
* @returns {Boolean}
*/

@@ -1110,4 +1077,3 @@ containsNonPairTag(textToCheck) {

/**
* @param {String} comment
* @returns {Array} or undefined if exception occurs when executing regex matching
* @returns array or undefined if exception occurs when executing regex matching
*/

@@ -1126,4 +1092,3 @@ extractLinksInMarkdownComment(comment) {

catch (e) {
// eslint-disable-next-line no-console
console.warn('Error parsing url in ExpensiMark.extractLinksInMarkdownComment', { error: e });
ExpensiMark.Log.alert('Error parsing url in ExpensiMark.extractLinksInMarkdownComment', { error: e });
return undefined;

@@ -1134,6 +1099,2 @@ }

* Compares two markdown comments and returns a list of the links removed in a new comment.
*
* @param {String} oldComment
* @param {String} newComment
* @returns {Array}
*/

@@ -1147,4 +1108,4 @@ getRemovedMarkdownLinks(oldComment, newComment) {

* Escapes the content of an HTML attribute value
* @param {String} content - string content that possible contains HTML
* @returns {String} - original MD content escaped for use in HTML attribute value
* @param content - string content that possible contains HTML
* @returns original MD content escaped for use in HTML attribute value
*/

@@ -1161,5 +1122,20 @@ escapeAttributeContent(content) {

}
/**
* Replaces text with a replacement based on a regex
* @param text - The text to replace
* @param regexp - The regex to match
* @param extras - The extras object
* @param replacement - The replacement string or function
* @returns The replaced text
*/
replaceTextWithExtras(text, regexp, extras, replacement) {
if (typeof replacement === 'function') {
// if the replacement is a function, we pass the extras object to it
return text.replace(regexp, (...args) => replacement(extras, ...args));
}
return text.replace(regexp, replacement);
}
}
ExpensiMark.Log = new Logger_1.default({
serverLoggingCallback: () => { },
serverLoggingCallback: () => undefined,
// eslint-disable-next-line no-console

@@ -1166,0 +1142,0 @@ clientLoggingCallback: (message) => console.warn(message),

{
"name": "expensify-common",
"version": "2.0.18",
"version": "2.0.19",
"author": "Expensify, Inc.",

@@ -5,0 +5,0 @@ "description": "Expensify libraries and components shared across different repos",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc