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.1.1 to 0.2.0

40

CHANGELOG.md

@@ -10,6 +10,46 @@ # Changelog

## [0.2.0] - 2021-03-30
### Changed
- **[BREAKING]** Description comments (`// msgdesc:`) have been removed in favor
of the `desc` option.
Before:
```js
// msgdesc: Home page
class HomePage {
hello() {
// msgdesc: Greeting to Earth
return msg(html`Hello World`);
}
goodbye() {
// msgdesc: Farewell to Earth
return msg(html`Goodbye World`);
}
}
```
After:
```js
class HomePage {
hello() {
return msg(html`Hello World`, {
desc: 'Home page / Greeting to Earth',
});
}
goodbye() {
return msg(html`Goodbye World`, {
desc: 'Home page / Farewell to Earth',
});
}
}
```
## [0.1.1] - 2021-03-30
### Changed
- Bumped dependency versions for `xmldom` and `@lit/localize`

@@ -16,0 +56,0 @@

6

lib/formatters/xlb.js

@@ -96,7 +96,7 @@ /**

bundle.appendChild(messagesNode);
for (const { name, contents, descStack } of sourceMessages) {
for (const { name, contents, desc } of sourceMessages) {
const messageNode = doc.createElement('msg');
messageNode.setAttribute('name', name);
if (descStack.length > 0) {
messageNode.setAttribute('desc', descStack.join(' / '));
if (desc) {
messageNode.setAttribute('desc', desc);
}

@@ -103,0 +103,0 @@ indent(messagesNode, 2);

@@ -160,3 +160,3 @@ /**

indent(body);
for (const { name, contents: sourceContents, descStack } of sourceMessages) {
for (const { name, contents: sourceContents, desc } of sourceMessages) {
// https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#trans-unit

@@ -167,6 +167,6 @@ const transUnit = doc.createElement('trans-unit');

transUnit.setAttribute('id', name);
if (descStack.length > 0) {
if (desc) {
// https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#note
const note = doc.createElement('note');
note.appendChild(doc.createTextNode(descStack.join(' / ')));
note.appendChild(doc.createTextNode(desc));
transUnit.appendChild(note);

@@ -173,0 +173,0 @@ indent(transUnit, 1);

@@ -38,6 +38,5 @@ /**

/**
* The stack of "msgdesc:" comments at the point where this message was
* extracted. Used for generating "desc" attributes in our XLB file.
* Description for this message.
*/
descStack: string[];
desc: string | undefined;
/**

@@ -44,0 +43,0 @@ * True if this message was tagged as a lit-html template, or was a function

@@ -25,7 +25,4 @@ /**

return messages.sort((a, b) => {
const descCompare = a.descStack
.join('')
.localeCompare(b.descStack.join(''));
if (descCompare !== 0) {
return descCompare;
if (a.desc ?? '' !== b.desc ?? '') {
return (a.desc ?? '').localeCompare(b.desc ?? '');
}

@@ -32,0 +29,0 @@ return a.file.fileName.localeCompare(b.file.fileName);

@@ -27,3 +27,3 @@ /**

id?: string;
args?: ts.NodeArray<ts.Expression>;
desc?: string;
}, ts.Diagnostic>;

@@ -30,0 +30,0 @@ interface ExtractedTemplate {

@@ -17,3 +17,3 @@ /**

for (const sourcefile of program.getSourceFiles()) {
extractMessagesFromNode(sourcefile, program, sourcefile, messages, errors, []);
extractMessagesFromNode(sourcefile, program, sourcefile, messages, errors);
}

@@ -33,12 +33,4 @@ const deduped = dedupeMessages(messages);

*/
function extractMessagesFromNode(file, program, node, messages, errors, descStack) {
const newDescs = extractMsgDescs(node, file.getFullText());
if (newDescs.length > 0) {
// Note we just make a copy of the stack each time we get a new description.
// This is a little simpler than modifying it in-place given that we have to
// de-duplicate. This could be a spot to optimize if we start handling
// humongous applications.
descStack = dedupeMsgDescs([...descStack, ...newDescs]);
}
const extractResult = extractMsg(file, program, node, descStack);
function extractMessagesFromNode(file, program, node, messages, errors) {
const extractResult = extractMsg(file, program, node);
if (extractResult.error) {

@@ -51,3 +43,3 @@ errors.push(extractResult.error);

ts.forEachChild(node, (node) => {
extractMessagesFromNode(file, program, node, messages, errors, descStack);
extractMessagesFromNode(file, program, node, messages, errors);
});

@@ -59,3 +51,3 @@ }

*/
function extractMsg(file, program, node, descStack) {
function extractMsg(file, program, node) {
if (!isMsgCall(node, program.getTypeChecker())) {

@@ -89,3 +81,5 @@ // We're not interested.

isLitTemplate,
descStack: descStack.map((desc) => desc.text),
// Note we pass node.parent because node is a CallExpression node, but the
// JSDoc tag will be attached to the parent Expression node.
desc: options.desc,
},

@@ -106,4 +100,4 @@ };

}
let id = undefined;
let args = undefined;
let id;
let desc;
for (const property of node.properties) {

@@ -141,3 +135,3 @@ // {

return {
error: createDiagnostic(file, property.initializer, `Options id property must be a non-empty string literal`),
error: createDiagnostic(file, property.initializer, `msg id option must be a non-empty string with no expressions`),
};

@@ -147,17 +141,18 @@ }

}
else if (name === 'args') {
if (!ts.isArrayLiteralExpression(property.initializer)) {
else if (name === 'desc') {
if (!ts.isStringLiteral(property.initializer) &&
!ts.isNoSubstitutionTemplateLiteral(property.initializer)) {
return {
error: createDiagnostic(file, property.initializer, `Options args property must be an array literal`),
error: createDiagnostic(file, property.initializer, `msg desc option must be a string with no expressions`),
};
}
args = property.initializer.elements;
desc = property.initializer.text;
}
else {
return {
error: createDiagnostic(file, property, `Options object property must be "id" or "args"`),
error: createDiagnostic(file, property, `Invalid msg option. Supported: id, desc`),
};
}
}
return { result: { id, args } };
return { result: { id, desc } };
}

@@ -379,40 +374,2 @@ /**

}
/**
* Look for "// msgdesc: foo" comments attached to the given node.
*/
function extractMsgDescs(node, fileText) {
const ranges = ts.getLeadingCommentRanges(fileText, node.getFullStart());
const descs = [];
if (ranges !== undefined) {
for (const range of ranges) {
const comment = fileText.slice(range.pos, range.end);
const match = comment.match(/.*msgdesc:\s*(.+)/);
if (match !== null) {
descs.push({ pos: range.pos, end: range.end, text: match[1].trim() });
}
}
}
return descs;
}
/**
* The way TypeScript treats comments in the AST means that it's possible for
* us to extract the exact same exact comment range multiple times when
* traversing certain AST structures (e.g. both for an "expression" node and
* some child node it has). De-duplicate these based on their source text
* positions.
*/
function dedupeMsgDescs(descs) {
// Since Maps preserve order, we can just pick a key that will be the same for
// duplicate comment ranges, populate the map, and then iterate through the
// values.
const map = new Map();
for (const desc of descs) {
const key = `${desc.pos}:${desc.end}`;
if (map.has(key)) {
continue;
}
map.set(key, desc);
}
return [...map.values()];
}
function replaceHtmlWithPlaceholders(html) {

@@ -419,0 +376,0 @@ const components = [];

{
"name": "@lit/localize-tools",
"version": "0.1.1",
"version": "0.2.0",
"publishConfig": {

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

"dependencies": {
"@lit/localize": "^0.8.0",
"@lit/localize": "^0.9.0",
"fs-extra": "^9.0.0",

@@ -43,0 +43,0 @@ "glob": "^7.1.6",

@@ -122,7 +122,7 @@ /**

bundle.appendChild(messagesNode);
for (const {name, contents, descStack} of sourceMessages) {
for (const {name, contents, desc} of sourceMessages) {
const messageNode = doc.createElement('msg');
messageNode.setAttribute('name', name);
if (descStack.length > 0) {
messageNode.setAttribute('desc', descStack.join(' / '));
if (desc) {
messageNode.setAttribute('desc', desc);
}

@@ -129,0 +129,0 @@ indent(messagesNode, 2);

@@ -223,3 +223,3 @@ /**

for (const {name, contents: sourceContents, descStack} of sourceMessages) {
for (const {name, contents: sourceContents, desc} of sourceMessages) {
// https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#trans-unit

@@ -231,6 +231,6 @@ const transUnit = doc.createElement('trans-unit');

if (descStack.length > 0) {
if (desc) {
// https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#note
const note = doc.createElement('note');
note.appendChild(doc.createTextNode(descStack.join(' / ')));
note.appendChild(doc.createTextNode(desc));
transUnit.appendChild(note);

@@ -237,0 +237,0 @@ indent(transUnit, 1);

@@ -44,6 +44,5 @@ /**

/**
* The stack of "msgdesc:" comments at the point where this message was
* extracted. Used for generating "desc" attributes in our XLB file.
* Description for this message.
*/
descStack: string[];
desc: string | undefined;

@@ -103,7 +102,4 @@ /**

return messages.sort((a, b) => {
const descCompare = a.descStack
.join('')
.localeCompare(b.descStack.join(''));
if (descCompare !== 0) {
return descCompare;
if (a.desc ?? '' !== b.desc ?? '') {
return (a.desc ?? '').localeCompare(b.desc ?? '');
}

@@ -110,0 +106,0 @@ return a.file.fileName.localeCompare(b.file.fileName);

@@ -26,10 +26,3 @@ /**

for (const sourcefile of program.getSourceFiles()) {
extractMessagesFromNode(
sourcefile,
program,
sourcefile,
messages,
errors,
[]
);
extractMessagesFromNode(sourcefile, program, sourcefile, messages, errors);
}

@@ -55,15 +48,5 @@ const deduped = dedupeMessages(messages);

messages: ProgramMessage[],
errors: ts.Diagnostic[],
descStack: MsgDesc[]
errors: ts.Diagnostic[]
): void {
const newDescs = extractMsgDescs(node, file.getFullText());
if (newDescs.length > 0) {
// Note we just make a copy of the stack each time we get a new description.
// This is a little simpler than modifying it in-place given that we have to
// de-duplicate. This could be a spot to optimize if we start handling
// humongous applications.
descStack = dedupeMsgDescs([...descStack, ...newDescs]);
}
const extractResult = extractMsg(file, program, node, descStack);
const extractResult = extractMsg(file, program, node);
if (extractResult.error) {

@@ -76,3 +59,3 @@ errors.push(extractResult.error);

ts.forEachChild(node, (node) => {
extractMessagesFromNode(file, program, node, messages, errors, descStack);
extractMessagesFromNode(file, program, node, messages, errors);
});

@@ -88,4 +71,3 @@ }

program: ts.Program,
node: ts.Node,
descStack: MsgDesc[]
node: ts.Node
): ResultOrError<ProgramMessage | undefined, ts.Diagnostic> {

@@ -131,3 +113,5 @@ if (!isMsgCall(node, program.getTypeChecker())) {

isLitTemplate,
descStack: descStack.map((desc) => desc.text),
// Note we pass node.parent because node is a CallExpression node, but the
// JSDoc tag will be attached to the parent Expression node.
desc: options.desc,
},

@@ -143,6 +127,3 @@ };

file: ts.SourceFile
): ResultOrError<
{id?: string; args?: ts.NodeArray<ts.Expression>},
ts.Diagnostic
> {
): ResultOrError<{id?: string; desc?: string}, ts.Diagnostic> {
if (node === undefined) {

@@ -161,4 +142,4 @@ return {result: {}};

let id: string | undefined = undefined;
let args: ts.NodeArray<ts.Expression> | undefined = undefined;
let id: string | undefined;
let desc: string | undefined;

@@ -211,3 +192,3 @@ for (const property of node.properties) {

property.initializer,
`Options id property must be a non-empty string literal`
`msg id option must be a non-empty string with no expressions`
),

@@ -217,4 +198,7 @@ };

id = property.initializer.text;
} else if (name === 'args') {
if (!ts.isArrayLiteralExpression(property.initializer)) {
} else if (name === 'desc') {
if (
!ts.isStringLiteral(property.initializer) &&
!ts.isNoSubstitutionTemplateLiteral(property.initializer)
) {
return {

@@ -224,7 +208,7 @@ error: createDiagnostic(

property.initializer,
`Options args property must be an array literal`
`msg desc option must be a string with no expressions`
),
};
}
args = property.initializer.elements;
desc = property.initializer.text;
} else {

@@ -235,3 +219,3 @@ return {

property,
`Options object property must be "id" or "args"`
`Invalid msg option. Supported: id, desc`
),

@@ -242,3 +226,3 @@ };

return {result: {id, args}};
return {result: {id, desc}};
}

@@ -510,55 +494,2 @@

/**
* A message description extracted from a TypeScript comment in a particular
* file.
*/
interface MsgDesc {
/** Where the comment begins in the source text. */
pos: number;
/** Where the comment ends in the source text. */
end: number;
/** The extracted description (the part after `// msgdesc: `) */
text: string;
}
/**
* Look for "// msgdesc: foo" comments attached to the given node.
*/
function extractMsgDescs(node: ts.Node, fileText: string): MsgDesc[] {
const ranges = ts.getLeadingCommentRanges(fileText, node.getFullStart());
const descs: MsgDesc[] = [];
if (ranges !== undefined) {
for (const range of ranges) {
const comment = fileText.slice(range.pos, range.end);
const match = comment.match(/.*msgdesc:\s*(.+)/);
if (match !== null) {
descs.push({pos: range.pos, end: range.end, text: match[1].trim()});
}
}
}
return descs;
}
/**
* The way TypeScript treats comments in the AST means that it's possible for
* us to extract the exact same exact comment range multiple times when
* traversing certain AST structures (e.g. both for an "expression" node and
* some child node it has). De-duplicate these based on their source text
* positions.
*/
function dedupeMsgDescs(descs: MsgDesc[]): MsgDesc[] {
// Since Maps preserve order, we can just pick a key that will be the same for
// duplicate comment ranges, populate the map, and then iterate through the
// values.
const map = new Map<string, MsgDesc>();
for (const desc of descs) {
const key = `${desc.pos}:${desc.end}`;
if (map.has(key)) {
continue;
}
map.set(key, desc);
}
return [...map.values()];
}
function replaceHtmlWithPlaceholders(

@@ -565,0 +496,0 @@ html: string

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