Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps: Bump sax-wasm from 2.2.4 to 3.0.3 #485

Merged
merged 13 commits into from
Jan 29, 2025
12 changes: 8 additions & 4 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"he": "^1.2.0",
"json-source-map": "^0.6.1",
"minimatch": "^10.0.1",
"sax-wasm": "2.2.4",
"sax-wasm": "^3.0.3",
"typescript": "^5.7.3",
"update-notifier": "^7.3.1",
"yargs": "^17.7.2"
Expand Down
11 changes: 6 additions & 5 deletions src/linter/dotLibrary/DotLibraryLinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,20 @@ export default class DotLibraryLinter {
return;
}

if (event === SaxEventType.OpenTag && !tag.selfClosing) {
tagsStack.push(tag.value);
} else if (event === SaxEventType.CloseTag && !tag.selfClosing) {
const serializedTag = tag.toJSON() as SaxTag;
if (event === SaxEventType.OpenTag && !serializedTag.selfClosing) {
tagsStack.push(serializedTag.name);
} else if (event === SaxEventType.CloseTag && !serializedTag.selfClosing) {
tagsStack.pop();
}

if (event === SaxEventType.CloseTag &&
tag.value === "libraryName") {
serializedTag.name === "libraryName") {
const isMatchingPath = libNamePath.length === tagsStack.length &&
libNamePath.every((lib, index) => lib === tagsStack[index]);

if (isMatchingPath) {
libs.add(tag);
libs.add(serializedTag);
}
}
});
Expand Down
11 changes: 6 additions & 5 deletions src/linter/html/HtmlReporter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {Tag as SaxTag, Text as SaxText, Position as SaxPosition} from "sax-wasm";
import {Position as SaxPosition, Tag as SaxTag, Text as SaxText} from "sax-wasm";
import LinterContext, {CoverageInfo, ResourcePath} from "../LinterContext.js";
import {MESSAGE} from "../messages.js";
import {MessageArgs} from "../MessageArgs.js";
import {isSaxParserToJSON, isSaxText} from "../../utils/xmlParser.js";

interface ReporterCoverageInfo extends CoverageInfo {
node: SaxTag;
Expand All @@ -25,10 +26,10 @@ export default class HtmlReporter {
throw new Error("Invalid arguments: Missing second argument");
}
let args: MessageArgs[M];
if (argsOrNode instanceof SaxTag) {
if (isSaxParserToJSON(argsOrNode)) {
node = argsOrNode;
args = null as unknown as MessageArgs[M];
} else if (argsOrNode instanceof SaxText) {
} else if (isSaxText(argsOrNode)) {
node = argsOrNode;
args = null as unknown as MessageArgs[M];
} else if (!node) {
Expand All @@ -38,7 +39,7 @@ export default class HtmlReporter {
}

let startPos: SaxPosition;
if (node instanceof SaxTag) {
if (isSaxParserToJSON(node)) {
startPos = node.openStart;
} else {
startPos = node.start;
Expand All @@ -51,7 +52,7 @@ export default class HtmlReporter {

addCoverageInfo({node, message, category}: ReporterCoverageInfo) {
let line = 0, column = 0, endLine = 0, endColumn = 0;
if (node instanceof SaxTag) {
if (isSaxParserToJSON(node)) {
({line, character: column} = node.openStart);
({line: endLine, character: endColumn} = node.closeEnd);
}
Expand Down
13 changes: 7 additions & 6 deletions src/linter/html/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ export async function extractHTMLTags(contentStream: ReadStream) {
if (!(tag instanceof SaxTag)) {
return;
}
const serializedTag = tag.toJSON() as SaxTag;
if (event === SaxEventType.OpenTag &&
tag.value === "link") {
if (tag.attributes.some((attr) => {
serializedTag.name === "link") {
if (serializedTag.attributes.some((attr) => {
return (attr.name.value === "rel" &&
attr.value.value === "stylesheet");
})) {
extractedTags.stylesheetLinkTags.push(tag);
extractedTags.stylesheetLinkTags.push(serializedTag);
};
} else if (event === SaxEventType.CloseTag &&
tag.value === "script") {
const isJSScriptTag = tag.attributes.every((attr) => {
serializedTag.name === "script") {
const isJSScriptTag = serializedTag.attributes.every((attr) => {
// The "type" attribute of the script tag should be
// 1. not set (default),
// 2. an empty string,
Expand All @@ -41,7 +42,7 @@ export async function extractHTMLTags(contentStream: ReadStream) {
].includes(attr.value.value.toLowerCase()));
});
if (isJSScriptTag) {
extractedTags.scriptTags.push(tag);
extractedTags.scriptTags.push(serializedTag);
}
}
});
Expand Down
11 changes: 5 additions & 6 deletions src/linter/html/transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import HtmlReporter from "./HtmlReporter.js";
import LinterContext, {ResourcePath, TranspileResult} from "../LinterContext.js";
import {taskStart} from "../../utils/perf.js";
import {MESSAGE} from "../messages.js";
import {Tag, Attribute} from "sax-wasm";
import {Attribute, Tag as SaxTag} from "sax-wasm";
import {deprecatedLibraries, deprecatedThemes} from "../../utils/deprecations.js";

export default async function transpileHtml(
Expand Down Expand Up @@ -34,8 +34,7 @@ export default async function transpileHtml(
});

stylesheetLinkTags.forEach((tag) => {
const href = tag.attributes.find((attr) =>
attr.name.value.toLowerCase() === "href");
const href = tag.attributes.find((attr) => attr.name.value.toLowerCase() === "href");
if (href) {
deprecatedThemes.forEach((themeName) => {
if (href.value.value.includes(`/themes/${themeName}/`)) {
Expand All @@ -54,7 +53,7 @@ export default async function transpileHtml(
}
}

function detectTestStarter(resourcePath: ResourcePath, scriptTags: Tag[], context: LinterContext) {
function detectTestStarter(resourcePath: ResourcePath, scriptTags: SaxTag[], context: LinterContext) {
const shouldBeMigrated = scriptTags.some((tag) => {
const isTestsuiteQunitFile = /testsuite(?:\.[a-z][a-z0-9-]*)*\.qunit\.html$/.test(resourcePath);
return (isTestsuiteQunitFile && !tag.attributes.some((attr) => {
Expand All @@ -74,7 +73,7 @@ function detectTestStarter(resourcePath: ResourcePath, scriptTags: Tag[], contex
}
}

function findBootstrapTag(tags: Tag[]): Tag | undefined {
function findBootstrapTag(tags: SaxTag[]): SaxTag | undefined {
// First search for script tag with id "sap-ui-bootstrap"
for (const tag of tags) {
for (const attr of tag.attributes) {
Expand Down Expand Up @@ -119,7 +118,7 @@ const aliasToAttr = new Map([
["data-sap-ui-xx-noless", "data-sap-ui-xx-no-less"],
]);

function lintBootstrapAttributes(tag: Tag, report: HtmlReporter) {
function lintBootstrapAttributes(tag: SaxTag, report: HtmlReporter) {
const attributes = new Set();
for (const attr of tag.attributes) {
let attributeName = attr.name.value.toLowerCase();
Expand Down
5 changes: 3 additions & 2 deletions src/linter/xmlTemplate/Parser.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Attribute as SaxAttribute, Tag as SaxTag, Position as SaxPosition} from "sax-wasm";
import {PositionDetail as SaxPosition} from "sax-wasm";
import he from "he";
import ViewGenerator from "./generator/ViewGenerator.js";
import FragmentGenerator from "./generator/FragmentGenerator.js";
Expand All @@ -11,6 +11,7 @@ import {MESSAGE} from "../messages.js";
import {ApiExtract} from "../../utils/ApiExtract.js";
import ControllerByIdInfo from "./ControllerByIdInfo.js";
import BindingLinter from "../binding/BindingLinter.js";
import {Tag as SaxTag} from "sax-wasm";
const log = getLogger("linter:xmlTemplate:Parser");

export type Namespace = string;
Expand Down Expand Up @@ -281,7 +282,7 @@ export default class Parser {
}

const attributes = new Set<AttributeDeclaration>();
tag.attributes.forEach((attr: SaxAttribute) => {
tag.attributes.forEach((attr) => {
const attrName = attr.name.value;
const attrValue = he.decode(attr.value.value);
// Extract namespaces immediately so we can resolve namespaced attributes in the next go
Expand Down
9 changes: 3 additions & 6 deletions src/linter/xmlTemplate/transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,14 @@ async function transpileXmlToJs(
const parser = new Parser(resourcePath, apiExtract, context, controllerByIdInfo);

// Initialize parser
const options = {highWaterMark: 32 * 1024}; // 32k chunks
const saxParser = new SAXParser(
SaxEventType.OpenTag | SaxEventType.CloseTag,
options);
const saxParser = new SAXParser(SaxEventType.OpenTag | SaxEventType.CloseTag);

saxParser.eventHandler = (event, tag) => {
if (tag instanceof SaxTag) {
if (event === SaxEventType.OpenTag) {
parser.pushTag(tag);
parser.pushTag(tag.toJSON() as SaxTag);
} else if (event === SaxEventType.CloseTag) {
parser.popTag(tag);
parser.popTag(tag.toJSON() as SaxTag);
}
}
};
Expand Down
26 changes: 22 additions & 4 deletions src/utils/xmlParser.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
import type {ReadStream} from "node:fs";
import {Detail, SaxEventType, SAXParser} from "sax-wasm";
import {Detail, Reader, SaxEventType, SAXParser, Tag, Text} from "sax-wasm";
import {finished} from "node:stream/promises";
import fs from "node:fs/promises";
import {createRequire} from "node:module";
const require = createRequire(import.meta.url);

export function isSaxParserToJSON(tag: unknown): tag is Tag {
const tagAsSaxParserToJSON = tag as Tag;
return !!tag &&
Object.prototype.hasOwnProperty.call(tagAsSaxParserToJSON, "openStart") &&
Object.prototype.hasOwnProperty.call(tagAsSaxParserToJSON, "openEnd") &&
Object.prototype.hasOwnProperty.call(tagAsSaxParserToJSON, "closeStart") &&
Object.prototype.hasOwnProperty.call(tagAsSaxParserToJSON, "closeEnd") &&
Object.prototype.hasOwnProperty.call(tagAsSaxParserToJSON, "attributes") &&
Object.prototype.hasOwnProperty.call(tagAsSaxParserToJSON, "textNodes");
}

export function isSaxText(tag: unknown): tag is Text {
return !!tag &&
Object.prototype.hasOwnProperty.call(tag, "start") &&
Object.prototype.hasOwnProperty.call(tag, "end") &&
Object.prototype.hasOwnProperty.call(tag, "value");
}

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

export async function parseXML(contentStream: ReadStream, parseHandler: (type: SaxEventType, tag: Detail) => void) {
const options = {highWaterMark: 32 * 1024}; // 32k chunks
export async function parseXML(
contentStream: ReadStream, parseHandler: (type: SaxEventType, tag: Reader<Detail>) => void) {
const saxWasmBuffer = await initSaxWasm();
const saxParser = new SAXParser(SaxEventType.CloseTag + SaxEventType.OpenTag, options);
const saxParser = new SAXParser(SaxEventType.CloseTag + SaxEventType.OpenTag);

saxParser.eventHandler = parseHandler;

Expand Down
2 changes: 1 addition & 1 deletion test/lib/utils/xmlParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ test("Test xmlParser with .library", async (t) => {
if (tag instanceof SaxTag &&
event === SaxEventType.CloseTag &&
tag.value === "libraryName") {
libs.push(tag);
libs.push(tag.toJSON() as SaxTag);
}
});

Expand Down
Loading