Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/big-swans-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@jackolope/lit-analyzer": patch
---

Update parse5 logic to use the built-in types instead of custom ones
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import type { HtmlNodeAttrAssignment } from "../../../../../types/html-node/html
import { HtmlNodeAttrAssignmentKind } from "../../../../../types/html-node/html-node-attr-assignment-types.js";
import type { HtmlNodeAttr } from "../../../../../types/html-node/html-node-attr-types.js";
import type { Range } from "../../../../../types/range.js";
import type { IP5NodeAttr, IP5TagNode } from "../parse-html-p5/parse-html-types.js";
import { getSourceLocation } from "../parse-html-p5/parse-html-types.js";
import type { ParseHtmlContext } from "./parse-html-context.js";
import type { DefaultTreeAdapterTypes, Token } from "parse5";

/**
* Parses a html attribute assignment.
Expand All @@ -15,8 +14,8 @@ import type { ParseHtmlContext } from "./parse-html-context.js";
* @param context
*/
export function parseHtmlAttrAssignment(
p5Node: IP5TagNode,
p5Attr: IP5NodeAttr,
p5Node: DefaultTreeAdapterTypes.Element,
p5Attr: Token.Attribute,
htmlAttr: HtmlNodeAttr,
context: ParseHtmlContext
): HtmlNodeAttrAssignment | undefined {
Expand Down Expand Up @@ -70,13 +69,18 @@ export function parseHtmlAttrAssignment(
}
}

function getAssignmentLocation(p5Node: IP5TagNode, p5Attr: IP5NodeAttr, htmlAttr: HtmlNodeAttr, context: ParseHtmlContext): Range | undefined {
const sourceLocation = getSourceLocation(p5Node);
function getAssignmentLocation(
p5Node: DefaultTreeAdapterTypes.Element,
p5Attr: Token.Attribute,
htmlAttr: HtmlNodeAttr,
context: ParseHtmlContext
): Range | undefined {
const sourceLocation = p5Node.sourceCodeLocation;
if (sourceLocation == null) {
return undefined;
}

const htmlAttrLocation = (sourceLocation.startTag.attrs || {})[p5Attr.name];
const htmlAttrLocation = ((sourceLocation.startTag as Token.LocationWithAttributes)?.attrs || {})[p5Attr.name];
if (htmlAttrLocation == null) return undefined;

const nameEndOffset = htmlAttr.location.name.end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@ import {
import type { HtmlNodeAttr, IHtmlNodeAttrBase, IHtmlNodeAttrSourceCodeLocation } from "../../../../../types/html-node/html-node-attr-types.js";
import { HtmlNodeAttrKind } from "../../../../../types/html-node/html-node-attr-types.js";
import { parseLitAttrName } from "../../../../../util/general-util.js";
import type { IP5NodeAttr, IP5TagNode } from "../parse-html-p5/parse-html-types.js";
import { getSourceLocation } from "../parse-html-p5/parse-html-types.js";
import { parseHtmlAttrAssignment } from "./parse-html-attr-assignment.js";
import type { ParseHtmlAttrContext } from "./parse-html-attr-context.js";
import type { DefaultTreeAdapterTypes, Token } from "parse5";

/**
* Creates multiple html attributes based on multiple p5Attributes.
* @param p5Node
* @param context
*/
export function parseHtmlNodeAttrs(p5Node: IP5TagNode, context: ParseHtmlAttrContext): HtmlNodeAttr[] {
export function parseHtmlNodeAttrs(p5Node: DefaultTreeAdapterTypes.Element, context: ParseHtmlAttrContext): HtmlNodeAttr[] {
return p5Node.attrs
.map(htmlAttr =>
parseHtmlNodeAttr(p5Node, htmlAttr, {
Expand All @@ -33,7 +32,11 @@ export function parseHtmlNodeAttrs(p5Node: IP5TagNode, context: ParseHtmlAttrCon
* @param p5Attr
* @param context
*/
export function parseHtmlNodeAttr(p5Node: IP5TagNode, p5Attr: IP5NodeAttr, context: ParseHtmlAttrContext): HtmlNodeAttr | undefined {
export function parseHtmlNodeAttr(
p5Node: DefaultTreeAdapterTypes.Element,
p5Attr: Token.Attribute,
context: ParseHtmlAttrContext
): HtmlNodeAttr | undefined {
const { htmlNode } = context;
const { name, modifier } = parseLitAttrName(p5Attr.name);

Expand Down Expand Up @@ -63,10 +66,14 @@ export function parseHtmlNodeAttr(p5Node: IP5TagNode, p5Attr: IP5NodeAttr, conte
* @param p5Attr
* @param context
*/
function makeHtmlAttrLocation(p5Node: IP5TagNode, p5Attr: IP5NodeAttr, context: ParseHtmlAttrContext): IHtmlNodeAttrSourceCodeLocation | undefined {
function makeHtmlAttrLocation(
p5Node: DefaultTreeAdapterTypes.Element,
p5Attr: Token.Attribute,
context: ParseHtmlAttrContext
): IHtmlNodeAttrSourceCodeLocation | undefined {
const { name, modifier } = parseLitAttrName(p5Attr.name);

const sourceLocation = getSourceLocation(p5Node);
const sourceLocation = p5Node.sourceCodeLocation;
if (sourceLocation == null) {
return undefined;
}
Expand All @@ -75,7 +82,7 @@ function makeHtmlAttrLocation(p5Node: IP5TagNode, p5Attr: IP5NodeAttr, context:
// Parse5 lowercases source code location attr keys but doesnt lowercase the attr name when it comes to svg.
// It would be correct not to lowercase the attr names because svg is case sensitive
const sourceCodeLocationName = `${p5Attr.prefix || ""}${(p5Attr.prefix && ":") || ""}${p5Attr.name}`.toLowerCase();
const htmlAttrLocation = (sourceLocation.startTag.attrs || {})[sourceCodeLocationName];
const htmlAttrLocation = ((sourceLocation.startTag as Token.LocationWithAttributes)?.attrs || {})[sourceCodeLocationName];
const start = htmlAttrLocation.startOffset;
const end = htmlAttrLocation.endOffset;
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { TS_IGNORE_FLAG } from "../../../../../constants.js";
import type { HtmlNode, IHtmlNodeBase, IHtmlNodeSourceCodeLocation } from "../../../../../types/html-node/html-node-types.js";
import { HtmlNodeKind } from "../../../../../types/html-node/html-node-types.js";
import { isCommentNode, isTagNode } from "../parse-html-p5/parse-html.js";
import type { IP5TagNode, P5Node } from "../parse-html-p5/parse-html-types.js";
import { getSourceLocation } from "../parse-html-p5/parse-html-types.js";
import type { DefaultTreeAdapterTypes } from "parse5";
import { parseHtmlNodeAttrs } from "./parse-html-attribute.js";
import type { ParseHtmlContext } from "./parse-html-context.js";

Expand All @@ -13,7 +12,7 @@ import type { ParseHtmlContext } from "./parse-html-context.js";
* @param parent
* @param context
*/
export function parseHtmlNodes(p5Nodes: P5Node[], parent: HtmlNode | undefined, context: ParseHtmlContext): HtmlNode[] {
export function parseHtmlNodes(p5Nodes: DefaultTreeAdapterTypes.Node[], parent: HtmlNode | undefined, context: ParseHtmlContext): HtmlNode[] {
const htmlNodes: HtmlNode[] = [];
let ignoreNextNode = false;
for (const p5Node of p5Nodes) {
Expand Down Expand Up @@ -45,9 +44,13 @@ export function parseHtmlNodes(p5Nodes: P5Node[], parent: HtmlNode | undefined,
* @param parent
* @param context
*/
export function parseHtmlNode(p5Node: IP5TagNode, parent: HtmlNode | undefined, context: ParseHtmlContext): HtmlNode | undefined {
export function parseHtmlNode(
p5Node: DefaultTreeAdapterTypes.Element,
parent: HtmlNode | undefined,
context: ParseHtmlContext
): HtmlNode | undefined {
// `sourceCodeLocation` will be undefined if the element was implicitly created by the parser.
if (getSourceLocation(p5Node) == null) return undefined;
if (p5Node.sourceCodeLocation == null) return undefined;

const htmlNodeBase: IHtmlNodeBase = {
tagName: p5Node.tagName.toLowerCase(),
Expand Down Expand Up @@ -75,19 +78,19 @@ export function parseHtmlNode(p5Node: IP5TagNode, parent: HtmlNode | undefined,
* @param p5Node
* @param context
*/
function makeHtmlNodeLocation(p5Node: IP5TagNode, context: ParseHtmlContext): IHtmlNodeSourceCodeLocation {
const loc = getSourceLocation(p5Node)!;
function makeHtmlNodeLocation(p5Node: DefaultTreeAdapterTypes.Element, context: ParseHtmlContext): IHtmlNodeSourceCodeLocation {
const loc = p5Node.sourceCodeLocation!;

return {
start: loc.startOffset,
end: loc.endOffset,
name: {
start: loc.startTag.startOffset + 1, // take '<' into account
end: loc.startTag.startOffset + 1 + p5Node.tagName.length
start: loc.startTag!.startOffset + 1, // take '<' into account
end: loc.startTag!.startOffset + 1 + p5Node.tagName.length
},
startTag: {
start: loc.startTag.startOffset,
end: loc.startTag.endOffset
start: loc.startTag!.startOffset,
end: loc.startTag!.endOffset
},
endTag:
loc.endTag == null
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,43 +1,42 @@
import type { IP5CommentNode, IP5DocumentFragmentNode, IP5NodeBase, IP5TagNode, IP5TextNode, P5Node } from "./parse-html-types.js";

const { parseFragment } = require("parse5");
import type { DefaultTreeAdapterTypes } from "parse5";
import { parseFragment } from "parse5";

/**
* Returns if a p5Node is a tag node.
* @param node
*/
export function isTagNode(node: P5Node): node is IP5TagNode {
export function isTagNode(node: DefaultTreeAdapterTypes.Node): node is DefaultTreeAdapterTypes.Element {
return !node.nodeName.includes("#");
}

/**
* Returns if a p5Node is a document fragment.
* @param node
*/
export function isDocumentFragmentNode(node: IP5NodeBase): node is IP5DocumentFragmentNode {
export function isDocumentFragmentNode(node: DefaultTreeAdapterTypes.Node): node is DefaultTreeAdapterTypes.DocumentFragment {
return node.nodeName === "#document-fragment";
}

/**
* Returns if a p5Node is a text node.
* @param node
*/
export function isTextNode(node: P5Node): node is IP5TextNode {
export function isTextNode(node: DefaultTreeAdapterTypes.Node): node is DefaultTreeAdapterTypes.TextNode {
return node.nodeName === "#text";
}

/**
* Returns if a p5Node is a comment node.
* @param node
*/
export function isCommentNode(node: P5Node): node is IP5CommentNode {
export function isCommentNode(node: DefaultTreeAdapterTypes.Node): node is DefaultTreeAdapterTypes.CommentNode {
return node.nodeName === "#comment";
}

/**
* Parse a html string into p5Nodes.
* @param html
*/
export function parseHtml(html: string): IP5DocumentFragmentNode {
return parseFragment(html, { sourceCodeLocationInfo: true, locationInfo: true });
export function parseHtml(html: string): DefaultTreeAdapterTypes.DocumentFragment {
return parseFragment(html, { sourceCodeLocationInfo: true });
}
Loading