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

@lit/localize-tools

Package Overview
Dependencies
Maintainers
7
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lit/localize-tools - npm Package Compare versions

Comparing version 0.5.0 to 0.6.0

50

CHANGELOG.md
# Changelog
## 0.6.0
### Minor Changes
- [#2405](https://github.com/lit/lit/pull/2405) [`4a4afa7b`](https://github.com/lit/lit/commit/4a4afa7bd394938102d8604ec6aff2e9eaf17c88) - **BREAKING** Update analysis to consider messages with same id **and** description to be identical (but no longer checks for expressions to be same) and improve error message on finding incompatible duplicates.
`lit-localize extract` will now error if multiple messages had the same text but different `desc` option. Be sure to add the same `desc` option for these messages to be considered the same translatable message or add different `id` options to differentiate them.
- [#2405](https://github.com/lit/lit/pull/2405) [`4a4afa7b`](https://github.com/lit/lit/commit/4a4afa7bd394938102d8604ec6aff2e9eaf17c88) - **BREAKING** (XLB format only) Add index to `name` attribute for `<ph>` tags for tracking placeholder locations.
XLB format users should run `lit-localize extract` to regenerate the `.xlb` file for the source locale and make sure the `<ph>` tags in other locale files have matching `name` attribute values to that of the newly generated source file.
### Patch Changes
- [#2402](https://github.com/lit/lit/pull/2402) [`a638841d`](https://github.com/lit/lit/commit/a638841d8ba76e43cf83a2516e2cfc7a9c2ce27e) - Trivial: reformat markdown files
## 0.5.0

@@ -162,15 +178,7 @@

// msgdesc: Greeting to Earth
return msg(
html`
Hello World
`
);
return msg(html`Hello World`);
}
goodbye() {
// msgdesc: Farewell to Earth
return msg(
html`
Goodbye World
`
);
return msg(html`Goodbye World`);
}

@@ -185,20 +193,10 @@ }

hello() {
return msg(
html`
Hello World
`,
{
desc: 'Home page / Greeting to Earth'
}
);
return msg(html`Hello World`, {
desc: 'Home page / Greeting to Earth',
});
}
goodbye() {
return msg(
html`
Goodbye World
`,
{
desc: 'Home page / Farewell to Earth'
}
);
return msg(html`Goodbye World`, {
desc: 'Home page / Farewell to Earth',
});
}

@@ -205,0 +203,0 @@ }

@@ -72,3 +72,4 @@ /**

}
contents.push({ untranslatable: phText.nodeValue || '' });
const index = Number(getNonEmptyAttributeOrThrow(child, 'name'));
contents.push({ untranslatable: phText.nodeValue || '', index });
}

@@ -105,2 +106,3 @@ else {

messagesNode.appendChild(messageNode);
let phIdx = 0;
for (const content of contents) {

@@ -113,2 +115,3 @@ if (typeof content === 'string') {

const ph = doc.createElement('ph');
ph.setAttribute('name', String(phIdx++));
ph.appendChild(doc.createTextNode(untranslatable));

@@ -115,0 +118,0 @@ messageNode.appendChild(ph);

@@ -85,3 +85,4 @@ /**

const phText = getNonEmptyAttributeOrThrow(child, 'equiv-text');
contents.push({ untranslatable: phText });
const index = Number(getNonEmptyAttributeOrThrow(child, 'id'));
contents.push({ untranslatable: phText, index });
}

@@ -96,3 +97,4 @@ else if (child.nodeType === doc.ELEMENT_NODE &&

}
contents.push({ untranslatable: phText.nodeValue || '' });
const index = Number(getNonEmptyAttributeOrThrow(child, 'id'));
contents.push({ untranslatable: phText.nodeValue || '', index });
}

@@ -99,0 +101,0 @@ else {

@@ -60,2 +60,3 @@ /**

untranslatable: string;
index: number;
}

@@ -62,0 +63,0 @@ /**

@@ -169,12 +169,3 @@ /**

const placeholderOrder = new Map();
const placeholderOrderKey = (placeholder, placeholderRelativeExpressionIdx) => JSON.stringify([
// TODO(aomarks) For XLIFF files, we have a unique numeric ID for each
// placeholder that would be preferable to use as the key here over the
// placeholder text itself. However, we don't currently have that ID for
// XLB. To add it to XLB, we need to do some research into the correct XML
// representation, and then make a breaking change. See
// https://github.com/lit/lit/issues/1897.
placeholder.untranslatable,
placeholderRelativeExpressionIdx,
]);
const placeholderOrderKey = (placeholder, placeholderRelativeExpressionIdx) => JSON.stringify([placeholder.index, placeholderRelativeExpressionIdx]);
let absIdx = 0;

@@ -181,0 +172,0 @@ for (const content of canon.contents) {

@@ -204,4 +204,4 @@ /**

}
const { tag } = templateResult.result;
let { template } = templateResult.result;
const { tag, contents, template } = templateResult.result;
let newTemplate = template;
const optionsResult = extractOptions(optionsArg, this.sourceFile);

@@ -213,36 +213,77 @@ if (optionsResult.error) {

const id = options.id ?? generateMsgIdFromAstNode(template, tag === 'html');
const sourceExpressions = new Map();
if (ts.isTemplateExpression(template)) {
for (const span of template.templateSpans) {
// TODO(aomarks) Support less brittle/more readable placeholder keys.
const key = this.sourceFile.text.slice(span.expression.pos, span.expression.end);
sourceExpressions.set(key, span.expression);
}
}
// If translations are available, replace the source template from the
// second argument with the corresponding translation.
if (this.translations !== undefined) {
const translation = this.translations.get(id);
if (translation !== undefined) {
// If translations are available, replace the source template from the
// second argument with the corresponding translation.
// Maps from <translation absolute expression index> to
// <[source placeholder index, placeholder-relative expression index]>.
const transExprToSourcePosition = new Map();
// Maps from <source placeholder index> to <the number of expressions in
// that placeholder>.
const placeholderExpressionCounts = new Map();
// The absolute position of each expression within the translated
// message.
let absTransExprIdx = 0;
// Maps source placeholder to their index.
const placeholdersByIndex = new Map();
for (let i = 0, phIdx = 0; i < contents.length; i++) {
const content = contents[i];
if (typeof content === 'object') {
placeholdersByIndex.set(phIdx++, content);
}
}
const templateLiteralBody = translation.contents
.map((content) => typeof content === 'string'
? escapeTextContentToEmbedInTemplateLiteral(content)
: content.untranslatable)
.map((content) => {
if (typeof content === 'string') {
return escapeTextContentToEmbedInTemplateLiteral(content);
}
const sourcePlaceholderIdx = content.index;
const matchingPlaceholder = placeholdersByIndex.get(sourcePlaceholderIdx);
if (matchingPlaceholder === undefined) {
throw new Error(`Placeholder from translation does not appear in source.` +
`\nLocale: ${this.locale}` +
`\nPlaceholder: ${content.untranslatable}`);
}
const parsedPlaceholder = parseStringAsTemplateLiteral(matchingPlaceholder.untranslatable);
if (ts.isTemplateExpression(parsedPlaceholder)) {
placeholderExpressionCounts.set(sourcePlaceholderIdx, parsedPlaceholder.templateSpans.length);
for (let i = 0; i < parsedPlaceholder.templateSpans.length; i++) {
const placeholderRelativeExprIdx = i;
transExprToSourcePosition.set(absTransExprIdx++, [
sourcePlaceholderIdx,
placeholderRelativeExprIdx,
]);
}
}
return matchingPlaceholder.untranslatable;
})
.join('');
template = parseStringAsTemplateLiteral(templateLiteralBody);
if (ts.isTemplateExpression(template)) {
newTemplate = parseStringAsTemplateLiteral(templateLiteralBody);
if (ts.isTemplateExpression(newTemplate)) {
const newParts = [];
newParts.push(template.head.text);
for (const span of template.templateSpans) {
const expressionKey = templateLiteralBody.slice(span.expression.pos - 1, span.expression.end - 1);
const sourceExpression = sourceExpressions.get(expressionKey);
if (sourceExpression === undefined) {
newParts.push(newTemplate.head.text);
for (let i = 0; i < newTemplate.templateSpans.length; i++) {
const span = newTemplate.templateSpans[i];
const srcPos = transExprToSourcePosition.get(i);
if (srcPos === undefined) {
const expressionText = templateLiteralBody.slice(span.expression.pos - 1, span.expression.end - 1);
throw new Error(`Expression in translation does not appear in source.` +
`\nLocale: ${this.locale}` +
`\nExpression: ${expressionKey}`);
`\nExpression: ${expressionText}`);
}
newParts.push(sourceExpression);
const [sourcePlaceholderIdx, placeholderRelativeExprIdx] = srcPos;
let absSourceExprIdx = placeholderRelativeExprIdx;
for (let j = 0; j < sourcePlaceholderIdx; j++) {
// Offset by the length of all preceding placeholder indexes.
absSourceExprIdx += placeholderExpressionCounts.get(j) ?? 0;
}
if (!ts.isTemplateExpression(template)) {
throw new Error('Internal error');
}
const sourceExpression = template.templateSpans[absSourceExprIdx];
newParts.push(sourceExpression.expression);
newParts.push(span.literal.text);
}
template = makeTemplateLiteral(newParts);
newTemplate = makeTemplateLiteral(newParts);
}

@@ -253,3 +294,3 @@ }

// Nothing more to do with a simple string.
if (ts.isStringLiteral(template)) {
if (ts.isStringLiteral(newTemplate)) {
if (tag === 'html') {

@@ -265,4 +306,4 @@ throw new KnownError('Internal error: string literal cannot be html-tagged');

// Generate: html`Hello <b>World</b>`
template = makeTemplateLiteral(this.recursivelyFlattenTemplate(template, tag === 'html'));
return tag === 'html' ? tagLit(template) : template;
newTemplate = makeTemplateLiteral(this.recursivelyFlattenTemplate(newTemplate, tag === 'html'));
return tag === 'html' ? tagLit(newTemplate) : newTemplate;
}

@@ -269,0 +310,0 @@ /**

@@ -342,2 +342,3 @@ /**

const phBuffer = [];
let phIdx = 0;
for (let i = 0; i < original.length; i++) {

@@ -356,3 +357,6 @@ const item = original[i];

// Flush the placeholder buffer.
combined.push({ untranslatable: phBuffer.splice(0).join('') });
combined.push({
untranslatable: phBuffer.splice(0).join(''),
index: phIdx++,
});
}

@@ -365,3 +369,3 @@ // Some translatable text.

// The final item was a placeholder, don't forget it.
combined.push({ untranslatable: phBuffer.join('') });
combined.push({ untranslatable: phBuffer.join(''), index: phIdx++ });
}

@@ -490,2 +494,3 @@ return combined;

const cache = new Map();
const duplicateCache = new Map();
for (const message of messages) {

@@ -497,7 +502,11 @@ const cached = cache.get(message.name);

else if (!messageEqual(message, cached)) {
errors.push(createDiagnostic(message.file, message.node, `Message ids must have the same default text wherever they are used`, [
createDiagnostic(cached.file, cached.node, 'This message id was already found here with different text.'),
]));
if (duplicateCache.get(cached.name) === undefined) {
duplicateCache.set(cached.name, [cached]);
}
duplicateCache.get(cached.name).push(message);
}
}
for (const [name, [originalMessage, ...rest]] of duplicateCache) {
errors.push(createDiagnostic(originalMessage.file, originalMessage.node, `The translation message with ID ${name} was defined in ${rest.length + 1} places, but with different strings or descriptions. If these messages should be translated together, make sure their strings and descriptions are identical, and consider factoring out a common variable or function. If they should be translated separately, add one or more {id: "..."} overrides to distinguish them.`, rest.map((message) => createDiagnostic(message.file, message.node, 'This message id was already found here with different text.'))));
}
return { messages: [...cache.values()], errors };

@@ -509,2 +518,5 @@ }

}
if (a.desc !== b.desc) {
return false;
}
for (let i = 0; i < a.contents.length; i++) {

@@ -524,7 +536,4 @@ if (!contentEqual(a.contents[i], b.contents[i])) {

}
if (typeof a === 'object') {
if (typeof b !== 'object') {
return false;
}
return a.untranslatable === b.untranslatable;
if (typeof a === 'object' && typeof b !== 'object') {
return false;
}

@@ -531,0 +540,0 @@ return true;

{
"name": "@lit/localize-tools",
"version": "0.5.0",
"version": "0.6.0",
"publishConfig": {

@@ -44,3 +44,3 @@ "access": "public"

"jsonschema": "^1.4.0",
"lit": "^2.0.0",
"lit": "^2.1.0",
"minimist": "^1.2.5",

@@ -52,4 +52,4 @@ "parse5": "^6.0.1",

"devDependencies": {
"@lit-labs/ssr": "^1.0.0",
"@lit/ts-transformers": "^1.0.2",
"@lit-labs/ssr": "^2.0.0",
"@lit/ts-transformers": "^1.1.0",
"@types/diff": "^5.0.0",

@@ -56,0 +56,0 @@ "@types/fs-extra": "^9.0.1",

@@ -93,3 +93,6 @@ /**

}
contents.push({untranslatable: phText.nodeValue || ''});
const index = Number(
getNonEmptyAttributeOrThrow(child as Element, 'name')
);
contents.push({untranslatable: phText.nodeValue || '', index});
} else {

@@ -131,2 +134,3 @@ throw new KnownError(

messagesNode.appendChild(messageNode);
let phIdx = 0;
for (const content of contents) {

@@ -138,2 +142,3 @@ if (typeof content === 'string') {

const ph = doc.createElement('ph');
ph.setAttribute('name', String(phIdx++));
ph.appendChild(doc.createTextNode(untranslatable));

@@ -140,0 +145,0 @@ messageNode.appendChild(ph);

@@ -119,3 +119,6 @@ /**

);
contents.push({untranslatable: phText});
const index = Number(
getNonEmptyAttributeOrThrow(child as Element, 'id')
);
contents.push({untranslatable: phText, index});
} else if (

@@ -135,3 +138,6 @@ child.nodeType === doc.ELEMENT_NODE &&

}
contents.push({untranslatable: phText.nodeValue || ''});
const index = Number(
getNonEmptyAttributeOrThrow(child as Element, 'id')
);
contents.push({untranslatable: phText.nodeValue || '', index});
} else {

@@ -138,0 +144,0 @@ throw new KnownError(

@@ -69,2 +69,3 @@ /**

untranslatable: string;
index: number;
// TODO(aomarks) Placeholders can also have names and examples, to help the

@@ -71,0 +72,0 @@ // translator understand the meaning of the placeholder. We could

@@ -231,13 +231,3 @@ /**

placeholderRelativeExpressionIdx: number
) =>
JSON.stringify([
// TODO(aomarks) For XLIFF files, we have a unique numeric ID for each
// placeholder that would be preferable to use as the key here over the
// placeholder text itself. However, we don't currently have that ID for
// XLB. To add it to XLB, we need to do some research into the correct XML
// representation, and then make a breaking change. See
// https://github.com/lit/lit/issues/1897.
placeholder.untranslatable,
placeholderRelativeExpressionIdx,
]);
) => JSON.stringify([placeholder.index, placeholderRelativeExpressionIdx]);

@@ -244,0 +234,0 @@ let absIdx = 0;

@@ -7,3 +7,3 @@ /**

import {Message, makeMessageIdMap} from '../messages.js';
import {Message, Placeholder, makeMessageIdMap} from '../messages.js';
import {writeLocaleCodesModule} from '../locales.js';

@@ -335,4 +335,4 @@ import type {Locale} from '../types/locale.js';

}
const {tag} = templateResult.result;
let {template} = templateResult.result;
const {tag, contents, template} = templateResult.result;
let newTemplate = template;

@@ -346,48 +346,97 @@ const optionsResult = extractOptions(optionsArg, this.sourceFile);

const sourceExpressions = new Map<string, ts.Expression>();
if (ts.isTemplateExpression(template)) {
for (const span of template.templateSpans) {
// TODO(aomarks) Support less brittle/more readable placeholder keys.
const key = this.sourceFile.text.slice(
span.expression.pos,
span.expression.end
);
sourceExpressions.set(key, span.expression);
}
}
// If translations are available, replace the source template from the
// second argument with the corresponding translation.
if (this.translations !== undefined) {
const translation = this.translations.get(id);
if (translation !== undefined) {
// If translations are available, replace the source template from the
// second argument with the corresponding translation.
// Maps from <translation absolute expression index> to
// <[source placeholder index, placeholder-relative expression index]>.
const transExprToSourcePosition = new Map<number, [number, number]>();
// Maps from <source placeholder index> to <the number of expressions in
// that placeholder>.
const placeholderExpressionCounts = new Map<number, number>();
// The absolute position of each expression within the translated
// message.
let absTransExprIdx = 0;
// Maps source placeholder to their index.
const placeholdersByIndex = new Map<number, Placeholder>();
for (let i = 0, phIdx = 0; i < contents.length; i++) {
const content = contents[i];
if (typeof content === 'object') {
placeholdersByIndex.set(phIdx++, content);
}
}
const templateLiteralBody = translation.contents
.map((content) =>
typeof content === 'string'
? escapeTextContentToEmbedInTemplateLiteral(content)
: content.untranslatable
)
.map((content) => {
if (typeof content === 'string') {
return escapeTextContentToEmbedInTemplateLiteral(content);
}
const sourcePlaceholderIdx = content.index;
const matchingPlaceholder =
placeholdersByIndex.get(sourcePlaceholderIdx);
if (matchingPlaceholder === undefined) {
throw new Error(
`Placeholder from translation does not appear in source.` +
`\nLocale: ${this.locale}` +
`\nPlaceholder: ${content.untranslatable}`
);
}
const parsedPlaceholder = parseStringAsTemplateLiteral(
matchingPlaceholder.untranslatable
);
if (ts.isTemplateExpression(parsedPlaceholder)) {
placeholderExpressionCounts.set(
sourcePlaceholderIdx,
parsedPlaceholder.templateSpans.length
);
for (let i = 0; i < parsedPlaceholder.templateSpans.length; i++) {
const placeholderRelativeExprIdx = i;
transExprToSourcePosition.set(absTransExprIdx++, [
sourcePlaceholderIdx,
placeholderRelativeExprIdx,
]);
}
}
return matchingPlaceholder.untranslatable;
})
.join('');
template = parseStringAsTemplateLiteral(templateLiteralBody);
if (ts.isTemplateExpression(template)) {
const newParts = [];
newParts.push(template.head.text);
for (const span of template.templateSpans) {
const expressionKey = templateLiteralBody.slice(
span.expression.pos - 1,
span.expression.end - 1
);
const sourceExpression = sourceExpressions.get(expressionKey);
if (sourceExpression === undefined) {
newTemplate = parseStringAsTemplateLiteral(templateLiteralBody);
if (ts.isTemplateExpression(newTemplate)) {
const newParts: Array<string | ts.Expression> = [];
newParts.push(newTemplate.head.text);
for (let i = 0; i < newTemplate.templateSpans.length; i++) {
const span = newTemplate.templateSpans[i];
const srcPos = transExprToSourcePosition.get(i);
if (srcPos === undefined) {
const expressionText = templateLiteralBody.slice(
span.expression.pos - 1,
span.expression.end - 1
);
throw new Error(
`Expression in translation does not appear in source.` +
`\nLocale: ${this.locale}` +
`\nExpression: ${expressionKey}`
`\nExpression: ${expressionText}`
);
}
newParts.push(sourceExpression);
const [sourcePlaceholderIdx, placeholderRelativeExprIdx] = srcPos;
let absSourceExprIdx = placeholderRelativeExprIdx;
for (let j = 0; j < sourcePlaceholderIdx; j++) {
// Offset by the length of all preceding placeholder indexes.
absSourceExprIdx += placeholderExpressionCounts.get(j) ?? 0;
}
if (!ts.isTemplateExpression(template)) {
throw new Error('Internal error');
}
const sourceExpression = template.templateSpans[absSourceExprIdx];
newParts.push(sourceExpression.expression);
newParts.push(span.literal.text);
}
template = makeTemplateLiteral(newParts);
newTemplate = makeTemplateLiteral(newParts);
}

@@ -399,3 +448,3 @@ }

// Nothing more to do with a simple string.
if (ts.isStringLiteral(template)) {
if (ts.isStringLiteral(newTemplate)) {
if (tag === 'html') {

@@ -414,6 +463,6 @@ throw new KnownError(

// Generate: html`Hello <b>World</b>`
template = makeTemplateLiteral(
this.recursivelyFlattenTemplate(template, tag === 'html')
newTemplate = makeTemplateLiteral(
this.recursivelyFlattenTemplate(newTemplate, tag === 'html')
);
return tag === 'html' ? tagLit(template) : template;
return tag === 'html' ? tagLit(newTemplate) : newTemplate;
}

@@ -420,0 +469,0 @@

@@ -9,3 +9,3 @@ /**

import * as parse5 from 'parse5';
import {ProgramMessage, Placeholder, Message} from './messages.js';
import {ProgramMessage, Placeholder} from './messages.js';
import {createDiagnostic} from './typescript.js';

@@ -403,3 +403,3 @@ import {

parts: Array<string | Expression>
): Array<string | Placeholder> {
): Array<string | Omit<Placeholder, 'index'>> {
const concatenatedHtml = parts

@@ -412,3 +412,3 @@ .map((part) =>

.join('');
const contents: Array<string | Placeholder> = [];
const contents: Array<string | Omit<Placeholder, 'index'>> = [];
for (const part of replaceHtmlWithPlaceholders(concatenatedHtml)) {

@@ -462,6 +462,7 @@ if (typeof part === 'string') {

function combineAdjacentPlaceholders(
original: Array<string | Placeholder>
original: Array<string | Omit<Placeholder, 'index'>>
): Array<string | Placeholder> {
const combined = [];
const phBuffer = [];
const combined: Array<string | Placeholder> = [];
const phBuffer: Array<string> = [];
let phIdx = 0;
for (let i = 0; i < original.length; i++) {

@@ -478,3 +479,6 @@ const item = original[i];

// Flush the placeholder buffer.
combined.push({untranslatable: phBuffer.splice(0).join('')});
combined.push({
untranslatable: phBuffer.splice(0).join(''),
index: phIdx++,
});
}

@@ -487,3 +491,3 @@ // Some translatable text.

// The final item was a placeholder, don't forget it.
combined.push({untranslatable: phBuffer.join('')});
combined.push({untranslatable: phBuffer.join(''), index: phIdx++});
}

@@ -495,4 +499,4 @@ return combined;

html: string
): Array<string | Placeholder> {
const components: Array<string | Placeholder> = [];
): Array<string | Omit<Placeholder, 'index'>> {
const components: Array<string | Omit<Placeholder, 'index'>> = [];

@@ -644,2 +648,3 @@ const traverse = (node: parse5.ChildNode): void => {

const cache = new Map<string, ProgramMessage>();
const duplicateCache = new Map<string, ProgramMessage[]>();
for (const message of messages) {

@@ -650,25 +655,36 @@ const cached = cache.get(message.name);

} else if (!messageEqual(message, cached)) {
errors.push(
createDiagnostic(
message.file,
message.node,
`Message ids must have the same default text wherever they are used`,
[
createDiagnostic(
cached.file,
cached.node,
'This message id was already found here with different text.'
),
]
)
);
if (duplicateCache.get(cached.name) === undefined) {
duplicateCache.set(cached.name, [cached]);
}
duplicateCache.get(cached.name)!.push(message);
}
}
for (const [name, [originalMessage, ...rest]] of duplicateCache) {
errors.push(
createDiagnostic(
originalMessage.file,
originalMessage.node,
`The translation message with ID ${name} was defined in ${
rest.length + 1
} places, but with different strings or descriptions. If these messages should be translated together, make sure their strings and descriptions are identical, and consider factoring out a common variable or function. If they should be translated separately, add one or more {id: "..."} overrides to distinguish them.`,
rest.map((message) =>
createDiagnostic(
message.file,
message.node,
'This message id was already found here with different text.'
)
)
)
);
}
return {messages: [...cache.values()], errors};
}
function messageEqual(a: Message, b: Message): boolean {
function messageEqual(a: ProgramMessage, b: ProgramMessage): boolean {
if (a.contents.length !== b.contents.length) {
return false;
}
if (a.desc !== b.desc) {
return false;
}
for (let i = 0; i < a.contents.length; i++) {

@@ -692,9 +708,6 @@ if (!contentEqual(a.contents[i], b.contents[i])) {

}
if (typeof a === 'object') {
if (typeof b !== 'object') {
return false;
}
return a.untranslatable === b.untranslatable;
if (typeof a === 'object' && typeof b !== 'object') {
return false;
}
return true;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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