Socket
Socket
Sign inDemoInstall

jsx-info

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsx-info - npm Package Compare versions

Comparing version 3.0.1 to 3.1.0

fixtures/prop-usage/multiplePropTypes.js

44

__tests__/api.test.ts

@@ -35,2 +35,30 @@ import * as path from "path";

test("analyze line-report directory [style]", async () => {
const directory = path.resolve(__dirname, "../fixtures/line-report");
const analysis = await analyze({
directory,
relativePaths: true,
components: ["div"],
prop: "style",
});
expect(analysis).toMatchSnapshot({
directory: expect.any(String),
elapsedTime: expect.any(Number),
});
});
test("analyze line-report directory [none]", async () => {
const directory = path.resolve(__dirname, "../fixtures/line-report");
const analysis = await analyze({
directory,
relativePaths: true,
components: ["div"],
prop: "none",
});
expect(analysis).toMatchSnapshot({
directory: expect.any(String),
elapsedTime: expect.any(Number),
});
});
test("analyze basic directory", async () => {

@@ -89,2 +117,3 @@ const directory = path.resolve(__dirname, "../fixtures/basic");

directory,
files: ["main.js"],
components: ["div"],

@@ -99,1 +128,16 @@ prop: "a",

});
test("analyze multiple prop types in prop-usage directory", async () => {
const directory = path.resolve(__dirname, "../fixtures/prop-usage");
const analysis = await analyze({
directory,
files: ["multiplePropTypes.js"],
components: ["div"],
prop: "value",
relativePaths: true,
});
expect(analysis).toMatchSnapshot({
directory: expect.any(String),
elapsedTime: expect.any(Number),
});
});

4

CHANGELOG.md

@@ -0,1 +1,5 @@

# v3.1.0
- Added `propValue` field `LineInfo`
# v3.0.1

@@ -2,0 +6,0 @@

4

dist/package.json
{
"name": "jsx-info",
"version": "3.0.1",
"version": "3.1.0",
"description": "displays a report of JSX component and prop usage",

@@ -11,3 +11,3 @@ "main": "dist/src/api.js",

"preversion": "npm run eslint && npm run prettier && npm test",
"postversion": "git push && git push --tags && npm publish",
"postversion": "git push --follow-tags && npm publish",
"start": "tsc --watch",

@@ -14,0 +14,0 @@ "upgrade": "npm-check --update",

import { ParserPlugin } from "@babel/parser";
import { JSXElement } from "@babel/types";
/** Options passed to `analyze` */

@@ -35,5 +36,33 @@ export interface AnalyzeOptions {

}
/**
* Prop values are tagged with a `type` field to facilitate understanding and
* extensibility as the project grows.
*
* - **none:** The prop wasn't used at the given location.
*
* - **expression:** Expression that can't be evaluated by scanning the code
* (e.g. array, object, function call, etc.).
*
* - **literal:** Literal value such as a string, boolean, number, etc. (NOTE:
* `undefined` is technically a variable, but I think most people expect it to
* be a literal).
*
* More types may be added in the future, if requested. I can see use cases for
* adding arrays and objects as values, though those have the potential to have
* expressions embedded within them. I still have too many questions about how
* to handle composite values like that, so I'm just not supporting them yet.
*/
export declare type PropValue = {
type: "none";
} | {
type: "expression";
} | {
type: "literal";
text: string;
value: number | string | boolean | undefined | null;
};
/** Information about a line where a prop was used */
export interface LineInfo {
propCode: string;
propValue: PropValue;
prettyCode: string;

@@ -70,1 +99,10 @@ startLoc: SourceLocation;

export declare function analyze({ babelPlugins, components, directory, files, gitignore, ignore, onFile, prop, relativePaths, }: AnalyzeOptions): Promise<Analysis>;
export interface ParseOptions {
typescript?: boolean;
babelPlugins?: ParserPlugin[];
onlyComponents?: string[];
onComponent?: (options: {
componentName: string;
node: JSXElement;
}) => void;
}

@@ -88,2 +88,4 @@ "use strict";

propCode: code.slice(node.start || 0, node.end || -1),
// JSXElement doesn't contain prop value
propValue: { type: "none" },
startLoc: node.loc.start,

@@ -117,15 +119,14 @@ endLoc: node.loc.end,

}
if (!match(prop.propValue)) {
if (prop.propValue.type === "literal" &&
!match(prop.propValue.text)) {
continue;
}
if ((!wantPropKey || prop.propName === wantPropKey) &&
match(prop.propValue)) {
reporter.addProp(componentName, prop.propName, {
propCode: prop.propCode,
startLoc: prop.startLoc,
endLoc: prop.endLoc,
prettyCode: formatPrettyCode(code, prop.startLoc.line, prop.endLoc.line),
filename: processFilename(filename),
});
}
reporter.addProp(componentName, prop.propName, {
propCode: prop.propCode,
propValue: prop.propValue,
startLoc: prop.startLoc,
endLoc: prop.endLoc,
prettyCode: formatPrettyCode(code, prop.startLoc.line, prop.endLoc.line),
filename: processFilename(filename),
});
}

@@ -176,21 +177,23 @@ }

}
const EXPRESSION = Symbol("formatPropValue.EXPRESSION");
function formatPropValue(value) {
if (value === null) {
return "true";
return { type: "literal", value: true, text: String(true) };
}
if (!value) {
return EXPRESSION;
}
switch (value.type) {
// TODO: Should we interpret anything else here?
// TODO: NaN, Infinity, -Infinity
case "Identifier":
if (value.name === "undefined") {
return { type: "literal", value: undefined, text: String(undefined) };
}
return { type: "expression" };
case "BooleanLiteral":
case "StringLiteral":
return value.value;
case "NumericLiteral":
return { type: "literal", value: value.value, text: String(value.value) };
case "NullLiteral":
return { type: "literal", value: null, text: String(null) };
case "JSXExpressionContainer":
return formatPropValue(value.expression);
case "NumericLiteral":
case "BooleanLiteral":
return String(value.value);
default:
return EXPRESSION;
return { type: "expression" };
}

@@ -197,0 +200,0 @@ }

{
"name": "jsx-info",
"version": "3.0.1",
"version": "3.1.0",
"description": "displays a report of JSX component and prop usage",

@@ -11,3 +11,3 @@ "main": "dist/src/api.js",

"preversion": "npm run eslint && npm run prettier && npm test",
"postversion": "git push && git push --tags && npm publish",
"postversion": "git push --follow-tags && npm publish",
"start": "tsc --watch",

@@ -14,0 +14,0 @@ "upgrade": "npm-check --update",

@@ -45,5 +45,33 @@ import { parse as babelParse, ParserPlugin } from "@babel/parser";

/**
* Prop values are tagged with a `type` field to facilitate understanding and
* extensibility as the project grows.
*
* - **none:** The prop wasn't used at the given location.
*
* - **expression:** Expression that can't be evaluated by scanning the code
* (e.g. array, object, function call, etc.).
*
* - **literal:** Literal value such as a string, boolean, number, etc. (NOTE:
* `undefined` is technically a variable, but I think most people expect it to
* be a literal).
*
* More types may be added in the future, if requested. I can see use cases for
* adding arrays and objects as values, though those have the potential to have
* expressions embedded within them. I still have too many questions about how
* to handle composite values like that, so I'm just not supporting them yet.
*/
export type PropValue =
| { type: "none" }
| { type: "expression" }
| {
type: "literal";
text: string;
value: number | string | boolean | undefined | null;
};
/** Information about a line where a prop was used */
export interface LineInfo {
propCode: string;
propValue: PropValue;
prettyCode: string;

@@ -147,2 +175,4 @@ startLoc: SourceLocation;

propCode: code.slice(node.start || 0, node.end || -1),
// JSXElement doesn't contain prop value
propValue: { type: "none" },
startLoc: node.loc.start,

@@ -161,3 +191,3 @@ endLoc: node.loc.end,

let wantPropKey = searchProp;
let match = (_value: string | symbol): boolean => true;
let match = (_value: string): boolean => true;
if (searchProp.includes("!=")) {

@@ -179,21 +209,20 @@ const index = searchProp.indexOf("!=");

}
if (!match(prop.propValue)) {
continue;
}
if (
(!wantPropKey || prop.propName === wantPropKey) &&
match(prop.propValue)
prop.propValue.type === "literal" &&
!match(prop.propValue.text)
) {
reporter.addProp(componentName, prop.propName, {
propCode: prop.propCode,
startLoc: prop.startLoc,
endLoc: prop.endLoc,
prettyCode: formatPrettyCode(
code,
prop.startLoc.line,
prop.endLoc.line
),
filename: processFilename(filename),
});
continue;
}
reporter.addProp(componentName, prop.propName, {
propCode: prop.propCode,
propValue: prop.propValue,
startLoc: prop.startLoc,
endLoc: prop.endLoc,
prettyCode: formatPrettyCode(
code,
prop.startLoc.line,
prop.endLoc.line
),
filename: processFilename(filename),
});
}

@@ -244,22 +273,23 @@ }

const EXPRESSION = Symbol("formatPropValue.EXPRESSION");
function formatPropValue(value: Node | null): string | symbol {
function formatPropValue(value: Node | null): PropValue {
if (value === null) {
return "true";
return { type: "literal", value: true, text: String(true) };
}
if (!value) {
return EXPRESSION;
}
switch (value.type) {
// TODO: Should we interpret anything else here?
// TODO: NaN, Infinity, -Infinity
case "Identifier":
if (value.name === "undefined") {
return { type: "literal", value: undefined, text: String(undefined) };
}
return { type: "expression" };
case "BooleanLiteral":
case "StringLiteral":
return value.value;
case "NumericLiteral":
return { type: "literal", value: value.value, text: String(value.value) };
case "NullLiteral":
return { type: "literal", value: null, text: String(null) };
case "JSXExpressionContainer":
return formatPropValue(value.expression);
case "NumericLiteral":
case "BooleanLiteral":
return String(value.value);
default:
return EXPRESSION;
return { type: "expression" };
}

@@ -283,3 +313,3 @@ }

function createProp(attributeNode: Node) {
function createProp(attributeNode: Node): string {
return getAttributeName(attributeNode);

@@ -299,7 +329,7 @@ }

function createComponent(componentNode: JSXElement) {
function createComponent(componentNode: JSXElement): string {
return getDottedName(componentNode.openingElement.name);
}
interface ParseOptions {
export interface ParseOptions {
typescript?: boolean;

@@ -410,3 +440,3 @@ babelPlugins?: ParserPlugin[];

addProp(componentName: string, propName: string, line: LineInfo) {
addProp(componentName: string, propName: string, line: LineInfo): void {
this._incrementProp(componentName, propName);

@@ -413,0 +443,0 @@ this._ensureLines(componentName, propName);

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