Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

Commit

Permalink
Use single node XPath where appropriate
Browse files Browse the repository at this point in the history
  • Loading branch information
eyelidlessness committed Mar 2, 2023
1 parent e480bfe commit 671d5c6
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 70 deletions.
15 changes: 2 additions & 13 deletions src/dom/abstract/Document.d.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
import type { Element } from './Element';
import type { Node } from './Node';

/** @package */
export interface NamespaceResolver {
lookupNamespaceURI(prefix: string): string | null;
}

/** @package */
export interface XPathResult {
ORDERED_NODE_SNAPSHOT_TYPE?: number;
snapshotItem?(index: number): Node | null;
snapshotLength?: number;
}
import type { XPathResult } from './XPathResult';

/** @package */
export interface Document {
Expand All @@ -27,7 +16,7 @@ export interface Document {
createElementNS(namespaceURI: string | null, name: string): Element;
evaluate(
xpathExpression: string,
contextNode: Node | Document,
contextNode: Node,
namespaceResolver: NamespaceResolver | null,
resultType: number
): XPathResult;
Expand Down
15 changes: 15 additions & 0 deletions src/dom/abstract/XPathResult.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/** @package */
export interface NamespaceResolver {
lookupNamespaceURI(prefix: string): string | null;
}

/** @package */
export class XPathResult {
static FIRST_ORDERED_NODE_TYPE: number;
static ORDERED_NODE_SNAPSHOT_TYPE: number;
readonly singleNodeValue: Node | null;
snapshotItem(index: number): Node | null;
readonly snapshotLength: number;
}

export type XPathResultType = number;
12 changes: 7 additions & 5 deletions src/dom/abstract/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { Attr as AbstractAttr } from './Attr';
import type {
Document as AbstractDocument,
NamespaceResolver as AbstractNamespaceResolver,
XPathResult as AbstractXPathResult,
} from './Document';
import type { Document as AbstractDocument } from './Document';
import type { DOMParser as AbstractDOMParser } from './DOMParser';
import type { Element as AbstractElement } from './Element';
import type { Node as AbstractNode } from './Node';
import type {
NamespaceResolver as AbstractNamespaceResolver,
XPathResult as AbstractXPathResult,
XPathResultType as AbstractXPathResultType,
} from './XPathResult';
import type { XSLTProcessor as AbstractXSLTProcessor } from './XSLTProcessor';

/** @package */
Expand All @@ -19,5 +20,6 @@ export namespace DOM {
export type Node = AbstractNode;
export type Element = AbstractElement;
export type XPathResult = AbstractXPathResult;
export type XPathResultType = AbstractXPathResultType;
export type XSLTProcessor = AbstractXSLTProcessor;
}
39 changes: 19 additions & 20 deletions src/dom/node/Document.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import type { ParentNode } from 'libxmljs';
import { libxmljs } from 'libxslt';
import { NAMESPACES } from '../../shared';
import type { DOM } from '../abstract';
import { NodeTypes } from '../shared';
import { XPathResult } from './XPathResult';

const { Document, Element } = libxmljs;

/** @package */
export const XPathResult = {
ORDERED_NODE_SNAPSHOT_TYPE: 6 as const,
snapshotItem: () => null,
snapshotLength: 0,
} satisfies DOM.XPathResult;

/** @package */
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DOMExtendedDocument extends DOM.Node {}
Expand Down Expand Up @@ -53,13 +46,10 @@ export class DOMExtendedDocument implements DOM.Document {
evaluate(
this: Document & DOMExtendedDocument,
xpathExpression: string,
contextNode: ParentNode,
contextNode: Document | Element,
namespaceResolver: DOM.NamespaceResolver | null,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - this is part of the interface!
// eslint-disable-next-line @typescript-eslint/no-unused-vars
resultType: XPathResult['ORDERED_NODE_SNAPSHOT_TYPE']
) {
resultType: number
): DOM.XPathResult {
const namespaces =
namespaceResolver == null
? undefined
Expand All @@ -71,19 +61,28 @@ export class DOMExtendedDocument implements DOM.Document {
)
);

const results = (contextNode ?? this).find(xpathExpression, namespaces);
if (resultType === XPathResult.FIRST_ORDERED_NODE_TYPE) {
const result = (contextNode ?? this).get(
xpathExpression,
namespaces
) as (Node & DOM.Node) | null;
const results = result == null ? [] : [result];

return new XPathResult(results);
}

const results = (contextNode ?? this).find(
xpathExpression,
namespaces
) as Array<Node & Element & DOM.Node>;

return {
snapshotItem: (index: number) => results[index],
snapshotLength: results.length,
};
return new XPathResult(results);
}
}

/* eslint-disable @typescript-eslint/no-redeclare */
type Document = InstanceType<typeof Document>;
type Element = InstanceType<typeof Element>;
export type XPathResult = typeof XPathResult;
/* eslint-enable @typescript-eslint/no-redeclare */

const { constructor: _, ...descriptors } = Object.getOwnPropertyDescriptors(
Expand Down
29 changes: 29 additions & 0 deletions src/dom/node/XPathResult.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { DOM } from '../abstract';

/** @package */
export class XPathResult implements DOM.XPathResult {
static ORDERED_NODE_SNAPSHOT_TYPE = 6 as const;

static FIRST_ORDERED_NODE_TYPE = 9 as const;

get singleNodeValue() {
return this.results[0] ?? null;
}

get snapshotLength() {
return this.results.length;
}

constructor(private results: Node[]) {}

snapshotItem(index: number) {
return this.results[index];
}
}

type XPathResultTypeKeys = {
[K in keyof XPathResult]: K extends `${string}_TYPE` ? K : never;
}[keyof XPathResult];

/** @package */
export type XPathResultType = XPathResult[XPathResultTypeKeys];
1 change: 1 addition & 0 deletions src/dom/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import './Document';
import './Node';
import './Element';

export * from './XPathResult';
export * from './DOMParser';
export * from './XSLTProcessor';
5 changes: 5 additions & 0 deletions src/dom/web/XPathResult.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { DOM } from '../abstract';

/** @package */
export const XPathResult =
globalThis.XPathResult satisfies new () => DOM.XPathResult;
1 change: 1 addition & 0 deletions src/dom/web/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './DOMParser';
export * from './XPathResult';
export * from './XSLTProcessor';
Loading

0 comments on commit 671d5c6

Please sign in to comment.