Skip to content

Commit

Permalink
feat: Implement html script linter
Browse files Browse the repository at this point in the history
  • Loading branch information
d3xter666 committed Mar 25, 2024
1 parent a3cd5bf commit 9608a89
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 13 deletions.
23 changes: 12 additions & 11 deletions src/detectors/transpilers/html/transpiler.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { ReadStream } from "node:fs";
import { Detail, SaxEventType, SAXParser, Tag as SaxTag } from "sax-wasm";
import { finished } from "node:stream/promises";
import type {ReadStream} from "node:fs";
import {Detail, SaxEventType, SAXParser, Tag as SaxTag} from "sax-wasm";
import {finished} from "node:stream/promises";
import fs from "node:fs/promises";
import { createRequire } from "node:module";
import {createRequire} from "node:module";
const require = createRequire(import.meta.url);

let saxWasmBuffer: Buffer;
Expand All @@ -15,7 +15,7 @@ async function initSaxWasm() {
return saxWasmBuffer;
}

export async function parseHtml(contentStream: ReadStream, parseHandler: (type: SaxEventType, tag: Detail) => void) {
async function parseHtml(contentStream: ReadStream, parseHandler: (type: SaxEventType, tag: Detail) => void) {
const options = { highWaterMark: 32 * 1024 }; // 32k chunks

Check failure on line 19 in src/detectors/transpilers/html/transpiler.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

There should be no space after '{'

Check failure on line 19 in src/detectors/transpilers/html/transpiler.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

There should be no space before '}'
const saxWasmBuffer = await initSaxWasm();
const saxParser = new SAXParser(SaxEventType.OpenTag | SaxEventType.CloseTag, options);
Expand Down Expand Up @@ -46,13 +46,14 @@ export async function parseHtml(contentStream: ReadStream, parseHandler: (type:
}

export async function extractScriptTags(contentStream: ReadStream) {
const scriptTags: SaxTag[] = [];
await parseHtml(contentStream, (event, tag) => {
if (tag instanceof SaxTag) {
if (event === SaxEventType.OpenTag) {
console.log(tag.value);
} else if (event === SaxEventType.CloseTag) {
console.log(tag.value);
}
if (tag instanceof SaxTag &&
event === SaxEventType.CloseTag &&
tag.value === "script") {
scriptTags.push(tag);
}
});

return scriptTags;
}

Check failure on line 59 in src/detectors/transpilers/html/transpiler.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

Newline required at end of file but not found
37 changes: 35 additions & 2 deletions src/linter/html/linter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,45 @@
import { taskStart } from "../../detectors/util/perf.js";
import {taskStart} from "../../detectors/util/perf.js";
import {extractScriptTags} from "../../detectors/transpilers/html/transpiler.js";
import {LintMessageSeverity} from "../../detectors/AbstractDetector.js";
import Reporter from "../å../detectors/Reporter.js";

import type { TranspileResult } from "../../detectors/transpilers/AbstractTranspiler.js";

Check failure on line 6 in src/linter/html/linter.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

There should be no space after '{'

Check failure on line 6 in src/linter/html/linter.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

There should be no space before '}'
import type { ReadStream } from "node:fs";

Check failure on line 7 in src/linter/html/linter.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

There should be no space after '{'

Check failure on line 7 in src/linter/html/linter.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

There should be no space before '}'


Check failure on line 9 in src/linter/html/linter.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

More than 1 blank line not allowed
export async function lintHtml(resourceName: string, contentStream: ReadStream): Promise<TranspileResult> {
const taskLintEnd = taskStart("Static lint", resourceName);
const report = new Reporter("", resourceName);

Check failure on line 12 in src/linter/html/linter.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

Unsafe assignment of an `any` value

Check failure on line 12 in src/linter/html/linter.ts

View workflow job for this annotation

GitHub Actions / General checks, tests and coverage reporting

Unsafe construction of an any type value

const scriptTags = await extractScriptTags(contentStream);
const jsScriptTags = scriptTags.filter((tag) => tag.attributes.every((attr) => {
// The "type" attribute of the script tag should be
// 1. not set (default),
// 2. an empty string,
// 3. or a JavaScript MIME type (text/javascript)
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type#attribute_is_not_set_default_an_empty_string_or_a_javascript_mime_type
return attr.name.value !== "type" ||
(attr.name.value === "type" &&
(attr.value.value === "" || attr.value.value === "text/javascript"));
}));


jsScriptTags.forEach((tag) => {
const scriptContent = tag.textNodes?.map((tNode) => tNode.value).join("").trim();

if (scriptContent) {
report.addMessage({
// node: `/sap.ui5/dependencies/libs/${libKey}`,
severity: LintMessageSeverity.Error,
ruleId: "ui5-linter-csp-compliance",
message: `Use of inline javascript`,
messageDetails: "In order to avoid CSP errors, avoid usage of inline javascript",
});
}
});

taskLintEnd();

return { messages: [], source: "", map: "" };
const {messages} = report.getReport();
return {messages, source: "", map: ""};
}

0 comments on commit 9608a89

Please sign in to comment.