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
6
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.3.2 to 0.3.3

50

lib/modes/runtime.js

@@ -140,9 +140,39 @@ /**

// For example, if some placeholders were reordered from [0 1 2] to [2 0 1],
// then we'll generate a template like: html`foo ${2} bar ${0} baz ${1}`
const placeholderOrder = new Map(canon.contents
.filter((value) => typeof value !== 'string')
.map((placeholder, idx) => [
// then we'll generate a template like: html`foo ${2} bar ${0} baz ${1}`.
//
// This map provides the absolute index within a template for each expression
// within the template. We identify each expression with the compound key
// [placeholder id, relative expression index].
//
// Note that any given XLIFF/XLB <ph> placeholder can contain zero, one, or
// many ${} expressions, so the index of the _placeholder_ is not the same as
// the index of the _expression_:
//
// <ph>&lt;a href="http://example.com/"></ph>
// <ph>&lt;a href="${/*0*/ url}"></ph>
// <ph>&lt;a href="${/*1*/ url}/${/*2*/ path}"></ph>
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,
idx,
]));
placeholderRelativeExpressionIdx,
]);
let absIdx = 0;
for (const content of canon.contents) {
if (typeof content === 'string') {
continue;
}
const template = parseStringAsTemplateLiteral(content.untranslatable);
if (ts.isNoSubstitutionTemplateLiteral(template)) {
continue;
}
for (let relIdx = 0; relIdx < template.templateSpans.length; relIdx++) {
placeholderOrder.set(placeholderOrderKey(content, relIdx), absIdx++);
}
}
const fragments = [];

@@ -160,6 +190,6 @@ for (const content of contents) {

fragments.push(template.head.text);
for (const span of template.templateSpans) {
// Substitute the value with the index (see note above).
fragments.push('${' + placeholderOrder.get(content.untranslatable) + '}');
fragments.push(span.literal.text);
for (let relIdx = 0; relIdx < template.templateSpans.length; relIdx++) {
const absIdx = placeholderOrder.get(placeholderOrderKey(content, relIdx));
fragments.push('${' + absIdx + '}');
fragments.push(template.templateSpans[relIdx].literal.text);
}

@@ -166,0 +196,0 @@ }

27

lib/modes/transform.js

@@ -124,3 +124,3 @@ /**

const moduleSymbol = this.typeChecker.getSymbolAtLocation(node.moduleSpecifier);
if (moduleSymbol && this.isLitLocalizeModule(moduleSymbol)) {
if (moduleSymbol && this.fileNameAppearsToBeLitLocalize(moduleSymbol)) {
return undefined;

@@ -183,3 +183,4 @@ }

const sourceFileSymbol = this.typeChecker.getSymbolAtLocation(sourceFile);
if (sourceFileSymbol && this.isLitLocalizeModule(sourceFileSymbol)) {
if (sourceFileSymbol &&
this.fileNameAppearsToBeLitLocalize(sourceFileSymbol)) {
return ts.createStringLiteral('lit-localize-status');

@@ -342,15 +343,13 @@ }

* Return whether the given symbol looks like one of the lit-localize modules
* (because it exports one of the special tagged functions).
* based on its filename. Note when we call this function, we're already
* strongly suspecting a lit-localize call.
*/
isLitLocalizeModule(moduleSymbol) {
if (!moduleSymbol.exports) {
return false;
}
const exports = moduleSymbol.exports.values();
for (const xport of exports) {
const type = this.typeChecker.getTypeAtLocation(xport.valueDeclaration);
const props = this.typeChecker.getPropertiesOfType(type);
if (props.some((prop) => prop.escapedName === '_LIT_LOCALIZE_MSG_' ||
prop.escapedName === '_LIT_LOCALIZE_CONTROLLER_FN_' ||
prop.escapedName === '_LIT_LOCALIZE_DECORATOR_')) {
fileNameAppearsToBeLitLocalize(moduleSymbol) {
// TODO(aomarks) Find a better way to implement this. We could probably just
// check for any file path matching '/@lit/localize/` -- however that will
// fail our tests because we import with a relative path in that case.
for (const decl of moduleSymbol.declarations) {
if (ts.isSourceFile(decl) &&
(decl.fileName.endsWith('/localize/lit-localize.d.ts') ||
decl.fileName.endsWith('/localize/internal/locale-status-event.d.ts'))) {
return true;

@@ -357,0 +356,0 @@ }

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

import { createDiagnostic } from './typescript.js';
import { generateMsgId, HASH_DELIMITER } from './id-generation.js';
import { generateMsgId, HASH_DELIMITER, } from '@lit/localize/internal/id-generation.js';
/**

@@ -259,3 +259,5 @@ * Extract translation messages from all files in a TypeScript program.

const EXPRESSION_START = `_START_LIT_LOCALIZE_EXPR_${EXPRESSION_RAND}_`;
const EXPRESSION_START_REGEXP = new RegExp(EXPRESSION_START, 'g');
const EXPRESSION_END = `_END_LIT_LOCALIZE_EXPR_${EXPRESSION_RAND}_`;
const EXPRESSION_END_REGEXP = new RegExp(EXPRESSION_END, 'g');
/**

@@ -316,4 +318,4 @@ * Our template is split apart based on template string literal expressions.

untranslatable: part.untranslatable
.replace(EXPRESSION_START, '${')
.replace(EXPRESSION_END, '}'),
.replace(EXPRESSION_START_REGEXP, '${')
.replace(EXPRESSION_END_REGEXP, '}'),
});

@@ -320,0 +322,0 @@ }

{
"name": "@lit/localize-tools",
"version": "0.3.2",
"version": "0.3.3",
"publishConfig": {

@@ -25,5 +25,5 @@ "access": "public"

"generate-json-schema": "typescript-json-schema tsconfig.schema.json ConfigFile --include=src/types/config.d.ts --required --noExtraProps > config.schema.json",
"test": "npm run build && npm run test:tape && npm run test:check-tsc",
"test:tape": "tape-es 'lib/tests/**/*.test.js' | tap-spec",
"test:update-goldens": "npm run build && UPDATE_TEST_GOLDENS=true npm run test:tape",
"test": "npm run build && npm run test:unit && npm run test:check-tsc",
"test:unit": "uvu lib/tests '\\.test\\.js$'",
"test:update-goldens": "npm run build && UPDATE_TEST_GOLDENS=true npm run test:unit",
"test:check-tsc": "ls testdata/*/output/tsconfig.json | xargs -n 1 tsc --noEmit --project",

@@ -60,3 +60,2 @@ "prepack": "npm run build"

"@types/prettier": "^2.0.1",
"@types/tape": "^4.13.0",
"@types/xmldom": "^0.1.29",

@@ -67,7 +66,5 @@ "diff": "^5.0.0",

"rimraf": "^3.0.2",
"tap-spec": "^5.0.0",
"tape": "^5.2.2",
"tape-es": "^1.2.11",
"typescript-json-schema": "^0.50.0"
"typescript-json-schema": "^0.50.0",
"uvu": "^0.5.1"
}
}

@@ -198,12 +198,46 @@ /**

// For example, if some placeholders were reordered from [0 1 2] to [2 0 1],
// then we'll generate a template like: html`foo ${2} bar ${0} baz ${1}`
const placeholderOrder = new Map<string, number>(
canon.contents
.filter((value) => typeof value !== 'string')
.map((placeholder, idx) => [
(placeholder as Placeholder).untranslatable,
idx,
])
);
// then we'll generate a template like: html`foo ${2} bar ${0} baz ${1}`.
//
// This map provides the absolute index within a template for each expression
// within the template. We identify each expression with the compound key
// [placeholder id, relative expression index].
//
// Note that any given XLIFF/XLB <ph> placeholder can contain zero, one, or
// many ${} expressions, so the index of the _placeholder_ is not the same as
// the index of the _expression_:
//
// <ph>&lt;a href="http://example.com/"></ph>
// <ph>&lt;a href="${/*0*/ url}"></ph>
// <ph>&lt;a href="${/*1*/ url}/${/*2*/ path}"></ph>
const placeholderOrder = new Map<string, number>();
const placeholderOrderKey = (
placeholder: Placeholder,
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,
]);
let absIdx = 0;
for (const content of canon.contents) {
if (typeof content === 'string') {
continue;
}
const template = parseStringAsTemplateLiteral(content.untranslatable);
if (ts.isNoSubstitutionTemplateLiteral(template)) {
continue;
}
for (let relIdx = 0; relIdx < template.templateSpans.length; relIdx++) {
placeholderOrder.set(placeholderOrderKey(content, relIdx), absIdx++);
}
}
const fragments = [];

@@ -219,8 +253,8 @@ for (const content of contents) {

fragments.push(template.head.text);
for (const span of template.templateSpans) {
// Substitute the value with the index (see note above).
fragments.push(
'${' + placeholderOrder.get(content.untranslatable) + '}'
);
fragments.push(span.literal.text);
for (let relIdx = 0; relIdx < template.templateSpans.length; relIdx++) {
const absIdx: number = placeholderOrder.get(
placeholderOrderKey(content, relIdx)
)!;
fragments.push('${' + absIdx + '}');
fragments.push(template.templateSpans[relIdx].literal.text);
}

@@ -227,0 +261,0 @@ }

@@ -203,3 +203,3 @@ /**

);
if (moduleSymbol && this.isLitLocalizeModule(moduleSymbol)) {
if (moduleSymbol && this.fileNameAppearsToBeLitLocalize(moduleSymbol)) {
return undefined;

@@ -301,3 +301,6 @@ }

);
if (sourceFileSymbol && this.isLitLocalizeModule(sourceFileSymbol)) {
if (
sourceFileSymbol &&
this.fileNameAppearsToBeLitLocalize(sourceFileSymbol)
) {
return ts.createStringLiteral('lit-localize-status');

@@ -503,21 +506,14 @@ }

* Return whether the given symbol looks like one of the lit-localize modules
* (because it exports one of the special tagged functions).
* based on its filename. Note when we call this function, we're already
* strongly suspecting a lit-localize call.
*/
isLitLocalizeModule(moduleSymbol: ts.Symbol): boolean {
if (!moduleSymbol.exports) {
return false;
}
const exports = moduleSymbol.exports.values();
for (const xport of exports as typeof exports & {
[Symbol.iterator](): Iterator<ts.Symbol>;
}) {
const type = this.typeChecker.getTypeAtLocation(xport.valueDeclaration);
const props = this.typeChecker.getPropertiesOfType(type);
fileNameAppearsToBeLitLocalize(moduleSymbol: ts.Symbol): boolean {
// TODO(aomarks) Find a better way to implement this. We could probably just
// check for any file path matching '/@lit/localize/` -- however that will
// fail our tests because we import with a relative path in that case.
for (const decl of moduleSymbol.declarations) {
if (
props.some(
(prop) =>
prop.escapedName === '_LIT_LOCALIZE_MSG_' ||
prop.escapedName === '_LIT_LOCALIZE_CONTROLLER_FN_' ||
prop.escapedName === '_LIT_LOCALIZE_DECORATOR_'
)
ts.isSourceFile(decl) &&
(decl.fileName.endsWith('/localize/lit-localize.d.ts') ||
decl.fileName.endsWith('/localize/internal/locale-status-event.d.ts'))
) {

@@ -524,0 +520,0 @@ return true;

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

import {createDiagnostic} from './typescript.js';
import {generateMsgId, HASH_DELIMITER} from './id-generation.js';
import {
generateMsgId,
HASH_DELIMITER,
} from '@lit/localize/internal/id-generation.js';

@@ -21,5 +24,6 @@ type ResultOrError<R, E> =

*/
export function extractMessagesFromProgram(
program: ts.Program
): {messages: ProgramMessage[]; errors: ts.Diagnostic[]} {
export function extractMessagesFromProgram(program: ts.Program): {
messages: ProgramMessage[];
errors: ts.Diagnostic[];
} {
const messages: ProgramMessage[] = [];

@@ -371,3 +375,5 @@ const errors: ts.Diagnostic[] = [];

const EXPRESSION_START = `_START_LIT_LOCALIZE_EXPR_${EXPRESSION_RAND}_`;
const EXPRESSION_START_REGEXP = new RegExp(EXPRESSION_START, 'g');
const EXPRESSION_END = `_END_LIT_LOCALIZE_EXPR_${EXPRESSION_RAND}_`;
const EXPRESSION_END_REGEXP = new RegExp(EXPRESSION_END, 'g');

@@ -431,4 +437,4 @@ /**

untranslatable: part.untranslatable
.replace(EXPRESSION_START, '${')
.replace(EXPRESSION_END, '}'),
.replace(EXPRESSION_START_REGEXP, '${')
.replace(EXPRESSION_END_REGEXP, '}'),
});

@@ -525,5 +531,6 @@ }

*/
function serializeOpenCloseTags(
node: parse5.ChildNode
): {open: string; close: string} {
function serializeOpenCloseTags(node: parse5.ChildNode): {
open: string;
close: string;
} {
const withoutChildren: parse5.ChildNode = {...node, childNodes: []};

@@ -629,5 +636,6 @@ const fakeParent = {childNodes: [withoutChildren]} as parse5.Node;

*/
function dedupeMessages(
messages: ProgramMessage[]
): {messages: ProgramMessage[]; errors: ts.Diagnostic[]} {
function dedupeMessages(messages: ProgramMessage[]): {
messages: ProgramMessage[];
errors: ts.Diagnostic[];
} {
const errors: ts.Diagnostic[] = [];

@@ -634,0 +642,0 @@ const cache = new Map<string, ProgramMessage>();

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