diff --git a/.eslintrc.json b/.eslintrc.json index 81f5c3aca..e0df25a9e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -36,7 +36,7 @@ "prettier" ], "rules": { - "@typescript-eslint/no-non-null-assertion": "warn", + "@typescript-eslint/no-non-null-assertion": "error", "@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/explicit-function-return-type": "error", "@typescript-eslint/no-unused-vars": "off" diff --git a/packages/parse5-html-rewriting-stream/lib/index.ts b/packages/parse5-html-rewriting-stream/lib/index.ts index e80303604..c6573687b 100644 --- a/packages/parse5-html-rewriting-stream/lib/index.ts +++ b/packages/parse5-html-rewriting-stream/lib/index.ts @@ -75,7 +75,8 @@ export class RewritingStream extends SAXParser { // Events protected override emitIfListenerExists(eventName: string, token: SaxToken): boolean { if (!super.emitIfListenerExists(eventName, token)) { - this.emitRaw(this._getRawHtml(token.sourceCodeLocation!)); + const html = token.sourceCodeLocation ? this._getRawHtml(token.sourceCodeLocation) : ''; + this.emitRaw(html); } // NOTE: don't skip new lines after `
` and other tags,
@@ -86,7 +87,8 @@ export class RewritingStream extends SAXParser {
 
     // Emitter API
     protected override _emitToken(eventName: string, token: SaxToken): void {
-        this.emit(eventName, token, this._getRawHtml(token.sourceCodeLocation!));
+        const html = token.sourceCodeLocation ? this._getRawHtml(token.sourceCodeLocation) : '';
+        this.emit(eventName, token, html);
     }
 
     /** Emits a serialized document type token into the output stream. */
diff --git a/packages/parse5-htmlparser2-tree-adapter/lib/index.ts b/packages/parse5-htmlparser2-tree-adapter/lib/index.ts
index 39f16c8c0..a2ce3b111 100644
--- a/packages/parse5-htmlparser2-tree-adapter/lib/index.ts
+++ b/packages/parse5-htmlparser2-tree-adapter/lib/index.ts
@@ -174,11 +174,16 @@ export function insertTextBefore(parentNode: NodeWithChildren, text: string, ref
 export function adoptAttributes(recipient: Element, attrs: Attribute[]): void {
     for (let i = 0; i < attrs.length; i++) {
         const attrName = attrs[i].name;
+        const { namespace, prefix } = attrs[i];
 
         if (typeof recipient.attribs[attrName] === 'undefined') {
             recipient.attribs[attrName] = attrs[i].value;
-            recipient['x-attribsNamespace']![attrName] = attrs[i].namespace!;
-            recipient['x-attribsPrefix']![attrName] = attrs[i].prefix!;
+            if (recipient['x-attribsNamespace'] && namespace) {
+                recipient['x-attribsNamespace'][attrName] = namespace;
+            }
+            if (recipient['x-attribsPrefix'] && prefix) {
+                recipient['x-attribsPrefix'][attrName] = prefix;
+            }
         }
     }
 }
diff --git a/packages/parse5-parser-stream/lib/index.ts b/packages/parse5-parser-stream/lib/index.ts
index d01f46b59..a2db609d6 100644
--- a/packages/parse5-parser-stream/lib/index.ts
+++ b/packages/parse5-parser-stream/lib/index.ts
@@ -76,7 +76,7 @@ export class ParserStream
         }
 
         while (this.pendingHtmlInsertions.length > 0) {
-            const html = this.pendingHtmlInsertions.pop()!;
+            const html = this.pendingHtmlInsertions.pop() ?? '';
 
             this.parser.tokenizer.insertHtmlAtCurrentPos(html);
         }
diff --git a/packages/parse5/lib/parser/formatting-element-list.ts b/packages/parse5/lib/parser/formatting-element-list.ts
index c90ca7542..1b5377f8e 100644
--- a/packages/parse5/lib/parser/formatting-element-list.ts
+++ b/packages/parse5/lib/parser/formatting-element-list.ts
@@ -114,7 +114,11 @@ export class FormattingElementList {
     }
 
     insertElementAfterBookmark(element: T['element'], token: TagToken): void {
-        const bookmarkIdx = this.entries.indexOf(this.bookmark!);
+        if (this.bookmark === null) {
+            return;
+        }
+
+        const bookmarkIdx = this.entries.indexOf(this.bookmark);
 
         this.entries.splice(bookmarkIdx, 0, {
             type: EntryType.Element,
diff --git a/packages/parse5/lib/parser/index.ts b/packages/parse5/lib/parser/index.ts
index b47fc1a48..7a6797072 100644
--- a/packages/parse5/lib/parser/index.ts
+++ b/packages/parse5/lib/parser/index.ts
@@ -294,8 +294,8 @@ export class Parser implements TokenHandler, Stack
     }
 
     onItemPop(node: T['parentNode'], isTop: boolean): void {
-        if (this.options.sourceCodeLocationInfo) {
-            this._setEndLocation(node, this.currentToken!);
+        if (this.options.sourceCodeLocationInfo && this.currentToken) {
+            this._setEndLocation(node, this.currentToken);
         }
 
         this.treeAdapter.onItemPop?.(node, this.openElements.current);
@@ -1729,9 +1729,13 @@ function startTagAfterHead(p: Parser, token: Ta
         case $.TEMPLATE:
         case $.TITLE: {
             p._err(token, ERR.abandonedHeadElementChild);
-            p.openElements.push(p.headElement!, $.HEAD);
+            if (p.headElement) {
+                p.openElements.push(p.headElement, $.HEAD);
+            }
             startTagInHead(p, token);
-            p.openElements.remove(p.headElement!);
+            if (p.headElement) {
+                p.openElements.remove(p.headElement);
+            }
             break;
         }
         case $.HEAD: {
diff --git a/packages/parse5/lib/tokenizer/preprocessor.ts b/packages/parse5/lib/tokenizer/preprocessor.ts
index b4165f29b..bc6204d80 100644
--- a/packages/parse5/lib/tokenizer/preprocessor.ts
+++ b/packages/parse5/lib/tokenizer/preprocessor.ts
@@ -235,7 +235,11 @@ export class Preprocessor {
         this.pos -= count;
 
         while (this.pos < this.lastGapPos) {
-            this.lastGapPos = this.gapStack.pop()!;
+            const lastGapPos = this.gapStack.pop();
+            if (lastGapPos === undefined) {
+                throw new Error('Gap stack was unexpectedly empty');
+            }
+            this.lastGapPos = lastGapPos;
             this.pos--;
         }