Skip to content

Commit

Permalink
feat: add removeHTMLComments option (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
fraxken authored Apr 5, 2023
1 parent 8d5850e commit 1af1621
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 23 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,20 +147,21 @@ This section describe all the possible warnings returned by JSXRay. Click on the

```ts
interface RuntimeOptions {
module?: boolean;
isMinified?: boolean;
module?: boolean;
isMinified?: boolean;
removeHTMLComments?: boolean;
}
```

The method take a first argument which is the code you want to analyse. It will return a Report Object:

```ts
interface Report {
dependencies: ASTDeps;
warnings: Warning[];
idsLengthAvg: number;
stringScore: number;
isOneLineRequire: boolean;
dependencies: ASTDeps;
warnings: Warning[];
idsLengthAvg: number;
stringScore: number;
isOneLineRequire: boolean;
}
```

Expand All @@ -171,8 +172,9 @@ interface Report {

```ts
interface RuntimeOptions {
module?: boolean;
isMinified?: boolean;
module?: boolean;
isMinified?: boolean;
removeHTMLComments?: boolean;
}
```

Expand Down
56 changes: 42 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import isMinified from "is-minified-code";
// Import Internal Dependencies
import Analysis from "./src/Analysis.js";
import { warnings } from "./src/warnings.js";
import * as utils from "./src/utils.js";

// CONSTANTS
const kMeriyahDefaultOptions = {
Expand All @@ -20,13 +21,19 @@ const kMeriyahDefaultOptions = {
};

export function runASTAnalysis(str, options = Object.create(null)) {
const { module = true, isMinified = false } = options;
const {
module = true,
isMinified = false,
removeHTMLComments = false
} = options;

// Note: if the file start with a shebang then we remove it because 'parseScript' may fail to parse it.
// Example: #!/usr/bin/env node
const strToAnalyze = str.charAt(0) === "#" ? str.slice(str.indexOf("\n")) : str;
const isEcmaScriptModule = Boolean(module);
const body = parseScriptExtended(strToAnalyze, isEcmaScriptModule);
const body = parseScriptExtended(strToAnalyze, {
isEcmaScriptModule: Boolean(module),
removeHTMLComments
});

const sastAnalysis = new Analysis();
sastAnalysis.analyzeSourceString(str);
Expand Down Expand Up @@ -57,14 +64,20 @@ export function runASTAnalysis(str, options = Object.create(null)) {

export async function runASTAnalysisOnFile(pathToFile, options = {}) {
try {
const { packageName = null, module = true } = options;
const {
packageName = null,
module = true,
removeHTMLComments = false
} = options;

const str = await fs.readFile(pathToFile, "utf-8");
const filePathString = pathToFile instanceof URL ? pathToFile.href : pathToFile;

const isMin = filePathString.includes(".min") || isMinified(str);
const data = runASTAnalysis(str, {
isMinified: isMin,
module: path.extname(filePathString) === ".mjs" ? true : module
module: path.extname(filePathString) === ".mjs" ? true : module,
removeHTMLComments
});
if (packageName !== null) {
data.dependencies.removeByName(packageName);
Expand All @@ -87,13 +100,24 @@ export async function runASTAnalysisOnFile(pathToFile, options = {}) {
}
}

function parseScriptExtended(strToAnalyze, isEcmaScriptModule) {
function parseScriptExtended(strToAnalyze, options = {}) {
const { isEcmaScriptModule, removeHTMLComments } = options;

/**
* @see https://github.com/NodeSecure/js-x-ray/issues/109
*/
const cleanedStrToAnalyze = removeHTMLComments ?
utils.removeHTMLComment(strToAnalyze) : strToAnalyze;

try {
const { body } = meriyah.parseScript(strToAnalyze, {
...kMeriyahDefaultOptions,
module: isEcmaScriptModule,
globalReturn: !isEcmaScriptModule
});
const { body } = meriyah.parseScript(
cleanedStrToAnalyze,
{
...kMeriyahDefaultOptions,
module: isEcmaScriptModule,
globalReturn: !isEcmaScriptModule
}
);

return body;
}
Expand All @@ -102,9 +126,13 @@ function parseScriptExtended(strToAnalyze, isEcmaScriptModule) {
error.description.includes("The import keyword") ||
error.description.includes("The export keyword")
)) {
const { body } = meriyah.parseScript(strToAnalyze, {
...kMeriyahDefaultOptions, module: true
});
const { body } = meriyah.parseScript(
cleanedStrToAnalyze,
{
...kMeriyahDefaultOptions,
module: true
}
);

return body;
}
Expand Down
4 changes: 4 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ export function extractNode(expectedType) {
}
};
}

export function removeHTMLComment(str) {
return str.replace(/<!--[\s\S]*?(?:-->)/g, "");
}
9 changes: 9 additions & 0 deletions test/fixtures/regress/html-comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- const foo = 5; //-->;

var bar;

<!--
// == fake comment == //

const yo = 5;
//-->;
23 changes: 23 additions & 0 deletions test/regress.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,26 @@ test("it should not crash for JSX", (tape) => {

tape.end();
});

// Regression test for https://github.com/NodeSecure/js-x-ray/issues/109
test("it should not crash for a JavaScript file containing HTML comments (and removeHTMLComments option enabled)", (tape) => {
const htmlComment = readFileSync(new URL("html-comments.js", FIXTURE_URL), "utf-8");
runASTAnalysis(htmlComment, {
removeHTMLComments: true
});

tape.end();
});

test("it should crash for a JavaScript file containing HTML comments", (tape) => {
const htmlComment = readFileSync(new URL("html-comments.js", FIXTURE_URL), "utf-8");
try {
runASTAnalysis(htmlComment);
tape.fail();
}
catch {
// do nothing
}

tape.end();
});
27 changes: 27 additions & 0 deletions test/utils.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Import Third-party Dependencies
import test from "tape";

// Import Internal Dependencies
import { removeHTMLComment } from "../src/utils.js";

test("removeHTMLComment() function should remove singleline HTML comment from string", (tape) => {
const result = removeHTMLComment(`
<!-- const yo = 5; -->
`);
tape.strictEqual(result.trim(), "");

tape.end();
});

test("removeHTMLComment() function should remove multiline HTML comment from string", (tape) => {
const result = removeHTMLComment(`
<!--
// == fake comment == //
const yo = 5;
//-->
`);
tape.strictEqual(result.trim(), "");

tape.end();
});
17 changes: 17 additions & 0 deletions types/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ export {
}

interface RuntimeOptions {
/**
* @default true
*/
module?: boolean;
/**
* @default false
*/
isMinified?: boolean;
/**
* @default false
*/
removeHTMLComments?: boolean;
}

interface Report {
Expand All @@ -27,7 +37,14 @@ interface Report {

interface RuntimeFileOptions {
packageName?: string;
/**
* @default true
*/
module?: boolean;
/**
* @default false
*/
removeHTMLComments?: boolean;
}

type ReportOnFile = {
Expand Down

0 comments on commit 1af1621

Please sign in to comment.