@markuplint/pretenders 0.0.23 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -1
- package/lib/cli.d.ts +10 -0
- package/lib/cli.js +10 -0
- package/lib/create-scanner.d.ts +8 -0
- package/lib/create-scanner.js +8 -0
- package/lib/dependency-mapper.d.ts +32 -0
- package/lib/dependency-mapper.js +29 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +7 -0
- package/lib/input.d.ts +7 -0
- package/lib/input.js +7 -0
- package/lib/jsx/create-identify.d.ts +11 -0
- package/lib/jsx/create-identify.js +11 -0
- package/lib/jsx/finder.d.ts +8 -0
- package/lib/jsx/finder.js +18 -0
- package/lib/jsx/get-attributes.d.ts +9 -0
- package/lib/jsx/get-attributes.js +9 -0
- package/lib/jsx/get-children.d.ts +8 -0
- package/lib/jsx/get-children.js +8 -0
- package/lib/jsx/index.d.ts +20 -0
- package/lib/jsx/index.js +24 -0
- package/lib/jsx/types.d.ts +14 -0
- package/lib/out.d.ts +7 -0
- package/lib/out.js +7 -0
- package/lib/pretender-director.d.ts +21 -0
- package/lib/pretender-director.js +21 -0
- package/lib/types.d.ts +24 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [0.0.
|
|
6
|
+
## [0.0.25](https://github.com/markuplint/markuplint/compare/@markuplint/pretenders@0.0.24...@markuplint/pretenders@0.0.25) (2026-02-10)
|
|
7
7
|
|
|
8
8
|
**Note:** Version bump only for package @markuplint/pretenders
|
|
9
9
|
|
|
10
|
+
## [0.0.24](https://github.com/markuplint/markuplint/compare/@markuplint/pretenders@0.0.23...@markuplint/pretenders@0.0.24) (2025-11-05)
|
|
10
11
|
|
|
12
|
+
**Note:** Version bump only for package @markuplint/pretenders
|
|
11
13
|
|
|
14
|
+
## [0.0.23](https://github.com/markuplint/markuplint/compare/@markuplint/pretenders@0.0.22...@markuplint/pretenders@0.0.23) (2025-08-24)
|
|
12
15
|
|
|
16
|
+
**Note:** Version bump only for package @markuplint/pretenders
|
|
13
17
|
|
|
14
18
|
## [0.0.22](https://github.com/markuplint/markuplint/compare/@markuplint/pretenders@0.0.21...@markuplint/pretenders@0.0.22) (2025-08-13)
|
|
15
19
|
|
package/lib/cli.d.ts
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI entry point for the pretenders scanner.
|
|
3
|
+
* Accepts file glob patterns as input arguments and writes discovered
|
|
4
|
+
* pretender mappings to a JSON output file.
|
|
5
|
+
*
|
|
6
|
+
* Usage: pretenders [options] <glob patterns...>
|
|
7
|
+
* Flags:
|
|
8
|
+
* -O, --out <path> Output file path (required)
|
|
9
|
+
* --ignore <names> Comma-separated list of component names to ignore
|
|
10
|
+
*/
|
|
1
11
|
export {};
|
package/lib/cli.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI entry point for the pretenders scanner.
|
|
3
|
+
* Accepts file glob patterns as input arguments and writes discovered
|
|
4
|
+
* pretender mappings to a JSON output file.
|
|
5
|
+
*
|
|
6
|
+
* Usage: pretenders [options] <glob patterns...>
|
|
7
|
+
* Flags:
|
|
8
|
+
* -O, --out <path> Output file path (required)
|
|
9
|
+
* --ignore <names> Comma-separated list of component names to ignore
|
|
10
|
+
*/
|
|
1
11
|
import path from 'node:path';
|
|
2
12
|
import meow from 'meow';
|
|
3
13
|
import { getFileList } from './input.js';
|
package/lib/create-scanner.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
import type { PretenderScannerScanMethod } from './types.js';
|
|
2
2
|
import type { PretenderScanOptions } from '@markuplint/ml-config';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a pretender scanner by wrapping a scan method with path validation.
|
|
5
|
+
* Ensures all provided file paths are absolute before delegating to the scan method.
|
|
6
|
+
*
|
|
7
|
+
* @template O - The scan options type, extending PretenderScanOptions
|
|
8
|
+
* @param method - The underlying scan method to wrap with validation
|
|
9
|
+
* @returns A wrapped scanner function that validates file paths and then invokes the scan method
|
|
10
|
+
*/
|
|
3
11
|
export declare function createScanner<O extends PretenderScanOptions = PretenderScanOptions>(method: PretenderScannerScanMethod<O>): (files: readonly string[], options?: O) => Promise<import("@markuplint/ml-config").Pretender[]>;
|
package/lib/create-scanner.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a pretender scanner by wrapping a scan method with path validation.
|
|
4
|
+
* Ensures all provided file paths are absolute before delegating to the scan method.
|
|
5
|
+
*
|
|
6
|
+
* @template O - The scan options type, extending PretenderScanOptions
|
|
7
|
+
* @param method - The underlying scan method to wrap with validation
|
|
8
|
+
* @returns A wrapped scanner function that validates file paths and then invokes the scan method
|
|
9
|
+
*/
|
|
2
10
|
export function createScanner(method) {
|
|
3
11
|
return (files, options) => {
|
|
4
12
|
for (const file of files) {
|
|
@@ -1,10 +1,42 @@
|
|
|
1
1
|
import type { Identifier, Identity } from './types.js';
|
|
2
2
|
import type { Pretender } from '@markuplint/ml-config';
|
|
3
|
+
/**
|
|
4
|
+
* Internal map structure storing component identifiers to their identity and source location.
|
|
5
|
+
*/
|
|
3
6
|
type PretenderDirectorMap = Map<Identifier, [identity: Identity, filePath?: string]>;
|
|
7
|
+
/**
|
|
8
|
+
* Collects and manages pretender mappings discovered during source file scanning.
|
|
9
|
+
* Acts as a registry where component-to-element relationships are added during
|
|
10
|
+
* traversal, then resolved into a flat list of pretenders with dependency linking.
|
|
11
|
+
*/
|
|
4
12
|
export declare class PretenderDirector {
|
|
5
13
|
#private;
|
|
14
|
+
/**
|
|
15
|
+
* Registers a component as a pretender mapping. If the identifier is already
|
|
16
|
+
* registered, the call is silently ignored (first definition wins).
|
|
17
|
+
*
|
|
18
|
+
* @param identifier - The component selector (e.g., component name)
|
|
19
|
+
* @param identity - The native HTML element the component renders as
|
|
20
|
+
* @param filePath - The relative file path where the component is defined
|
|
21
|
+
* @param line - The line number of the component declaration
|
|
22
|
+
* @param col - The column number of the component declaration
|
|
23
|
+
*/
|
|
6
24
|
add(identifier: Identifier, identity: Identity, filePath: string, line: number, col: number): void;
|
|
25
|
+
/**
|
|
26
|
+
* Resolves all registered mappings into a sorted array of Pretender objects.
|
|
27
|
+
* Follows component-to-component chains to determine the final native element identity.
|
|
28
|
+
*
|
|
29
|
+
* @returns A sorted array of resolved Pretender objects
|
|
30
|
+
*/
|
|
7
31
|
getPretenders(): Pretender[];
|
|
8
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolves a map of component-to-identity mappings into a flat array of Pretender objects.
|
|
35
|
+
* Follows chains where one component wraps another (e.g., MyButton -> Button -> button)
|
|
36
|
+
* until a native element is reached or a recursive loop is detected.
|
|
37
|
+
*
|
|
38
|
+
* @param map - The map of component identifiers to their identity and file path
|
|
39
|
+
* @returns A sorted array of fully resolved Pretender objects
|
|
40
|
+
*/
|
|
9
41
|
export declare function dependencyMapper(map: Readonly<PretenderDirectorMap>): Pretender[];
|
|
10
42
|
export {};
|
package/lib/dependency-mapper.js
CHANGED
|
@@ -4,21 +4,50 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
6
|
var _PretenderDirector_map;
|
|
7
|
+
/**
|
|
8
|
+
* Collects and manages pretender mappings discovered during source file scanning.
|
|
9
|
+
* Acts as a registry where component-to-element relationships are added during
|
|
10
|
+
* traversal, then resolved into a flat list of pretenders with dependency linking.
|
|
11
|
+
*/
|
|
7
12
|
export class PretenderDirector {
|
|
8
13
|
constructor() {
|
|
9
14
|
_PretenderDirector_map.set(this, new Map());
|
|
10
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Registers a component as a pretender mapping. If the identifier is already
|
|
18
|
+
* registered, the call is silently ignored (first definition wins).
|
|
19
|
+
*
|
|
20
|
+
* @param identifier - The component selector (e.g., component name)
|
|
21
|
+
* @param identity - The native HTML element the component renders as
|
|
22
|
+
* @param filePath - The relative file path where the component is defined
|
|
23
|
+
* @param line - The line number of the component declaration
|
|
24
|
+
* @param col - The column number of the component declaration
|
|
25
|
+
*/
|
|
11
26
|
add(identifier, identity, filePath, line, col) {
|
|
12
27
|
if (__classPrivateFieldGet(this, _PretenderDirector_map, "f").has(identifier)) {
|
|
13
28
|
return;
|
|
14
29
|
}
|
|
15
30
|
__classPrivateFieldGet(this, _PretenderDirector_map, "f").set(identifier, [identity, `${filePath}:${line}:${col}`]);
|
|
16
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolves all registered mappings into a sorted array of Pretender objects.
|
|
34
|
+
* Follows component-to-component chains to determine the final native element identity.
|
|
35
|
+
*
|
|
36
|
+
* @returns A sorted array of resolved Pretender objects
|
|
37
|
+
*/
|
|
17
38
|
getPretenders() {
|
|
18
39
|
return dependencyMapper(__classPrivateFieldGet(this, _PretenderDirector_map, "f"));
|
|
19
40
|
}
|
|
20
41
|
}
|
|
21
42
|
_PretenderDirector_map = new WeakMap();
|
|
43
|
+
/**
|
|
44
|
+
* Resolves a map of component-to-identity mappings into a flat array of Pretender objects.
|
|
45
|
+
* Follows chains where one component wraps another (e.g., MyButton -> Button -> button)
|
|
46
|
+
* until a native element is reached or a recursive loop is detected.
|
|
47
|
+
*
|
|
48
|
+
* @param map - The map of component identifiers to their identity and file path
|
|
49
|
+
* @returns A sorted array of fully resolved Pretender objects
|
|
50
|
+
*/
|
|
22
51
|
export function dependencyMapper(map) {
|
|
23
52
|
const linkedPretenders = [];
|
|
24
53
|
const collection = [...map.entries()];
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/pretenders
|
|
3
|
+
*
|
|
4
|
+
* Provides scanning utilities for detecting component-to-element mappings (pretenders)
|
|
5
|
+
* in JSX/TSX source files. Pretenders allow markuplint to understand which native HTML
|
|
6
|
+
* elements a component renders, enabling accurate linting of component-based code.
|
|
7
|
+
*/
|
|
1
8
|
export { jsxScanner } from './jsx/index.js';
|
|
2
9
|
export type * from './types.js';
|
package/lib/index.js
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/pretenders
|
|
3
|
+
*
|
|
4
|
+
* Provides scanning utilities for detecting component-to-element mappings (pretenders)
|
|
5
|
+
* in JSX/TSX source files. Pretenders allow markuplint to understand which native HTML
|
|
6
|
+
* elements a component renders, enabling accurate linting of component-based code.
|
|
7
|
+
*/
|
|
1
8
|
export { jsxScanner } from './jsx/index.js';
|
package/lib/input.d.ts
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves a list of file path patterns (possibly relative or glob patterns)
|
|
3
|
+
* into a flat array of matching absolute file paths.
|
|
4
|
+
*
|
|
5
|
+
* @param input - An array of file paths or glob patterns to resolve
|
|
6
|
+
* @returns A flat array of resolved absolute file paths matching the input patterns
|
|
7
|
+
*/
|
|
1
8
|
export declare function getFileList(input: readonly string[]): Promise<string[]>;
|
package/lib/input.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { glob } from 'glob';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves a list of file path patterns (possibly relative or glob patterns)
|
|
5
|
+
* into a flat array of matching absolute file paths.
|
|
6
|
+
*
|
|
7
|
+
* @param input - An array of file paths or glob patterns to resolve
|
|
8
|
+
* @returns A flat array of resolved absolute file paths matching the input patterns
|
|
9
|
+
*/
|
|
3
10
|
export async function getFileList(input) {
|
|
4
11
|
const result = await Promise.all(input
|
|
5
12
|
.map(filePath => {
|
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
import type { Attr } from '../types.js';
|
|
2
2
|
import type { Slot } from '@markuplint/ml-config';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a pretender identity from a JSX element's tag name, attributes, and slots.
|
|
5
|
+
* If the element has no attributes, returns just the tag name string.
|
|
6
|
+
* Otherwise, returns a detailed identity object including attributes, slots,
|
|
7
|
+
* and whether the element inherits spread attributes.
|
|
8
|
+
*
|
|
9
|
+
* @param tagName - The HTML element or component tag name
|
|
10
|
+
* @param attrs - The attributes discovered on the JSX element
|
|
11
|
+
* @param slots - The child slots discovered within the JSX element
|
|
12
|
+
* @returns A simple tag name string or a detailed Identity object
|
|
13
|
+
*/
|
|
3
14
|
export declare function createIndentity(tagName: string, attrs: readonly Attr[], slots: readonly Slot[]): string | import("@markuplint/ml-config").OriginalNode;
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a pretender identity from a JSX element's tag name, attributes, and slots.
|
|
3
|
+
* If the element has no attributes, returns just the tag name string.
|
|
4
|
+
* Otherwise, returns a detailed identity object including attributes, slots,
|
|
5
|
+
* and whether the element inherits spread attributes.
|
|
6
|
+
*
|
|
7
|
+
* @param tagName - The HTML element or component tag name
|
|
8
|
+
* @param attrs - The attributes discovered on the JSX element
|
|
9
|
+
* @param slots - The child slots discovered within the JSX element
|
|
10
|
+
* @returns A simple tag name string or a detailed Identity object
|
|
11
|
+
*/
|
|
1
12
|
export function createIndentity(tagName, attrs, slots) {
|
|
2
13
|
if (attrs.length === 0) {
|
|
3
14
|
return tagName;
|
package/lib/jsx/finder.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
import type { Node, SourceFile } from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a recursive AST node finder bound to a specific source file.
|
|
4
|
+
* The returned `find` function traverses the AST depth-first, invoking the
|
|
5
|
+
* visitor callback on the first node that matches the type guard predicate.
|
|
6
|
+
*
|
|
7
|
+
* @param sourceFile - The TypeScript source file context for the traversal
|
|
8
|
+
* @returns A `find` function that searches for nodes matching a type guard and invokes a visitor
|
|
9
|
+
*/
|
|
2
10
|
export declare function finder(sourceFile: SourceFile): <N extends Node>(node: Node, is: (node: Node) => node is N, visit: (node: N, sourceFile: SourceFile) => void) => void;
|
package/lib/jsx/finder.js
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
const { forEachChild } = ts;
|
|
3
|
+
/**
|
|
4
|
+
* Creates a recursive AST node finder bound to a specific source file.
|
|
5
|
+
* The returned `find` function traverses the AST depth-first, invoking the
|
|
6
|
+
* visitor callback on the first node that matches the type guard predicate.
|
|
7
|
+
*
|
|
8
|
+
* @param sourceFile - The TypeScript source file context for the traversal
|
|
9
|
+
* @returns A `find` function that searches for nodes matching a type guard and invokes a visitor
|
|
10
|
+
*/
|
|
3
11
|
export function finder(
|
|
4
12
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
5
13
|
sourceFile) {
|
|
14
|
+
/**
|
|
15
|
+
* Recursively searches the AST starting from the given node.
|
|
16
|
+
* If the node matches the type guard, the visitor is called immediately
|
|
17
|
+
* and recursion stops for that branch. Otherwise, all children are traversed.
|
|
18
|
+
*
|
|
19
|
+
* @template N - The specific AST node type to find
|
|
20
|
+
* @param node - The starting AST node to search from
|
|
21
|
+
* @param is - A TypeScript type guard predicate to match desired nodes
|
|
22
|
+
* @param visit - A callback invoked with each matched node and the source file
|
|
23
|
+
*/
|
|
6
24
|
return function find(
|
|
7
25
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
8
26
|
node, is, visit) {
|
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
import type { Attr } from '../types.js';
|
|
2
2
|
import type { JsxOpeningElement, JsxSelfClosingElement, SourceFile } from 'typescript';
|
|
3
|
+
/**
|
|
4
|
+
* Extracts all attributes from a JSX opening or self-closing element.
|
|
5
|
+
* Classifies each attribute by its node type: static (string literal value),
|
|
6
|
+
* boolean (no value), dynamic (expression value), or spread ({...props}).
|
|
7
|
+
*
|
|
8
|
+
* @param el - The JSX opening or self-closing element to extract attributes from
|
|
9
|
+
* @param sourceFile - The TypeScript source file containing the element
|
|
10
|
+
* @returns An array of Attr objects representing all discovered attributes
|
|
11
|
+
*/
|
|
3
12
|
export declare function getAttributes(el: JsxOpeningElement | JsxSelfClosingElement, sourceFile: SourceFile): Attr[];
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { finder } from './finder.js';
|
|
3
3
|
const { isJsxAttribute, isJsxExpression, isJsxSpreadAttribute, isStringLiteral } = ts;
|
|
4
|
+
/**
|
|
5
|
+
* Extracts all attributes from a JSX opening or self-closing element.
|
|
6
|
+
* Classifies each attribute by its node type: static (string literal value),
|
|
7
|
+
* boolean (no value), dynamic (expression value), or spread ({...props}).
|
|
8
|
+
*
|
|
9
|
+
* @param el - The JSX opening or self-closing element to extract attributes from
|
|
10
|
+
* @param sourceFile - The TypeScript source file containing the element
|
|
11
|
+
* @returns An array of Attr objects representing all discovered attributes
|
|
12
|
+
*/
|
|
4
13
|
export function getAttributes(
|
|
5
14
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
6
15
|
el,
|
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
import type { Slot } from '@markuplint/ml-config';
|
|
2
2
|
import type { JsxOpeningElement, JsxSelfClosingElement, SourceFile } from 'typescript';
|
|
3
|
+
/**
|
|
4
|
+
* Extracts child slot information from a JSX element.
|
|
5
|
+
* Currently returns an empty array as child slot extraction is not yet implemented.
|
|
6
|
+
*
|
|
7
|
+
* @param el - The JSX opening or self-closing element to extract children from
|
|
8
|
+
* @param sourceFile - The TypeScript source file containing the element
|
|
9
|
+
* @returns An array of Slot objects representing discovered child slots
|
|
10
|
+
*/
|
|
3
11
|
export declare function getChildren(el: JsxOpeningElement | JsxSelfClosingElement, sourceFile: SourceFile): Slot[];
|
package/lib/jsx/get-children.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// import { finder } from './finder.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts child slot information from a JSX element.
|
|
4
|
+
* Currently returns an empty array as child slot extraction is not yet implemented.
|
|
5
|
+
*
|
|
6
|
+
* @param el - The JSX opening or self-closing element to extract children from
|
|
7
|
+
* @param sourceFile - The TypeScript source file containing the element
|
|
8
|
+
* @returns An array of Slot objects representing discovered child slots
|
|
9
|
+
*/
|
|
2
10
|
export function getChildren(
|
|
3
11
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
4
12
|
el,
|
package/lib/jsx/index.d.ts
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/pretenders/jsx
|
|
3
|
+
*
|
|
4
|
+
* JSX/TSX scanner for discovering pretender mappings. Analyzes component source
|
|
5
|
+
* files using the TypeScript compiler API to determine which native HTML elements
|
|
6
|
+
* each component renders, including support for styled-components, HOC wrappers,
|
|
7
|
+
* and fragment providers.
|
|
8
|
+
*/
|
|
1
9
|
import type { PretenderScanJSXOptions } from './types.js';
|
|
2
10
|
import type { Pretender } from '@markuplint/ml-config';
|
|
11
|
+
/**
|
|
12
|
+
* A scanner function that analyzes JSX/TSX source files to discover pretender mappings.
|
|
13
|
+
* Uses the TypeScript compiler API to parse and traverse the AST, identifying component
|
|
14
|
+
* definitions and the native HTML elements they render.
|
|
15
|
+
*
|
|
16
|
+
* Supports:
|
|
17
|
+
* - Function components (function declarations and arrow functions)
|
|
18
|
+
* - Styled-components (`styled.element` tagged templates)
|
|
19
|
+
* - HOC / wrapper function patterns
|
|
20
|
+
* - Fragment and provider component transparency
|
|
21
|
+
* - `@pretends null` JSDoc tag to opt out a component
|
|
22
|
+
*/
|
|
3
23
|
export declare const jsxScanner: (files: readonly string[], options?: PretenderScanJSXOptions | undefined) => Promise<Pretender[]>;
|
package/lib/jsx/index.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/pretenders/jsx
|
|
3
|
+
*
|
|
4
|
+
* JSX/TSX scanner for discovering pretender mappings. Analyzes component source
|
|
5
|
+
* files using the TypeScript compiler API to determine which native HTML elements
|
|
6
|
+
* each component renders, including support for styled-components, HOC wrappers,
|
|
7
|
+
* and fragment providers.
|
|
8
|
+
*/
|
|
1
9
|
import path from 'node:path';
|
|
2
10
|
import { getPosition } from '@markuplint/parser-utils/location';
|
|
3
11
|
import ts from 'typescript';
|
|
@@ -8,6 +16,10 @@ import { finder } from './finder.js';
|
|
|
8
16
|
import { getAttributes } from './get-attributes.js';
|
|
9
17
|
import { getChildren } from './get-children.js';
|
|
10
18
|
const { createProgram, forEachChild, isArrowFunction, isCallExpression, isFunctionDeclaration, isJsxFragment, isJsxOpeningElement, isJsxSelfClosingElement, isReturnStatement, isTaggedTemplateExpression, isVariableDeclaration, JsxEmit, } = ts;
|
|
19
|
+
/**
|
|
20
|
+
* Default options for the JSX scanner, including built-in patterns
|
|
21
|
+
* for styled-components and provider components.
|
|
22
|
+
*/
|
|
11
23
|
const defaultOptions = {
|
|
12
24
|
cwd: process.cwd(),
|
|
13
25
|
asFragment: [/(?:^|\.)provider$/i],
|
|
@@ -20,6 +32,18 @@ const defaultOptions = {
|
|
|
20
32
|
],
|
|
21
33
|
extendingWrapper: [],
|
|
22
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* A scanner function that analyzes JSX/TSX source files to discover pretender mappings.
|
|
37
|
+
* Uses the TypeScript compiler API to parse and traverse the AST, identifying component
|
|
38
|
+
* definitions and the native HTML elements they render.
|
|
39
|
+
*
|
|
40
|
+
* Supports:
|
|
41
|
+
* - Function components (function declarations and arrow functions)
|
|
42
|
+
* - Styled-components (`styled.element` tagged templates)
|
|
43
|
+
* - HOC / wrapper function patterns
|
|
44
|
+
* - Fragment and provider component transparency
|
|
45
|
+
* - `@pretends null` JSDoc tag to opt out a component
|
|
46
|
+
*/
|
|
23
47
|
export const jsxScanner = createScanner((files, options = defaultOptions) => {
|
|
24
48
|
const { cwd = defaultOptions.cwd, ignoreComponentNames = defaultOptions.ignoreComponentNames, asFragment = defaultOptions.asFragment, taggedStylingComponent = defaultOptions.taggedStylingComponent, extendingWrapper = defaultOptions.extendingWrapper, } = options;
|
|
25
49
|
const director = new PretenderDirector();
|
package/lib/jsx/types.d.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import type { PretenderScanOptions } from '@markuplint/ml-config';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for the JSX pretender scanner.
|
|
4
|
+
* Extends the base scan options with JSX-specific settings for handling
|
|
5
|
+
* fragments, styled-components, and wrapper patterns.
|
|
6
|
+
*/
|
|
2
7
|
export interface PretenderScanJSXOptions extends PretenderScanOptions {
|
|
8
|
+
/** Patterns matching component names to treat as transparent fragments (children are scanned instead) */
|
|
3
9
|
asFragment?: readonly (Readonly<RegExp> | string)[];
|
|
10
|
+
/** Patterns matching tagged template expressions for CSS-in-JS libraries (e.g., styled.button) */
|
|
4
11
|
taggedStylingComponent?: readonly (Readonly<RegExp> | string)[];
|
|
12
|
+
/** Patterns matching HOC or wrapper function calls that extend another component */
|
|
5
13
|
extendingWrapper?: readonly (string | Readonly<RegExp> | ExtendingWrapperCallerOptions)[];
|
|
6
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for identifying a wrapper/HOC function call and which
|
|
17
|
+
* argument position contains the wrapped component reference.
|
|
18
|
+
*/
|
|
7
19
|
export type ExtendingWrapperCallerOptions = {
|
|
20
|
+
/** Pattern to match the wrapper function identifier */
|
|
8
21
|
readonly identifier: string | Readonly<RegExp>;
|
|
22
|
+
/** The 1-based argument position that contains the wrapped component */
|
|
9
23
|
readonly numberOfArgument: number;
|
|
10
24
|
};
|
package/lib/out.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
import type { Pretender } from '@markuplint/ml-config';
|
|
2
|
+
/**
|
|
3
|
+
* Writes an array of pretender mappings to a JSON file in the PretenderFileData format.
|
|
4
|
+
* The output file includes the package version and the pretender data array.
|
|
5
|
+
*
|
|
6
|
+
* @param filePath - The absolute path of the output JSON file to write
|
|
7
|
+
* @param data - The array of Pretender objects to serialize
|
|
8
|
+
*/
|
|
2
9
|
export declare function out(filePath: string, data: readonly Pretender[]): Promise<void>;
|
package/lib/out.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { writeFile } from 'node:fs/promises';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
const require = createRequire(import.meta.url);
|
|
4
|
+
/**
|
|
5
|
+
* Writes an array of pretender mappings to a JSON file in the PretenderFileData format.
|
|
6
|
+
* The output file includes the package version and the pretender data array.
|
|
7
|
+
*
|
|
8
|
+
* @param filePath - The absolute path of the output JSON file to write
|
|
9
|
+
* @param data - The array of Pretender objects to serialize
|
|
10
|
+
*/
|
|
4
11
|
export async function out(filePath, data) {
|
|
5
12
|
await writeFile(filePath, JSON.stringify({
|
|
6
13
|
version: require('../package.json').version,
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
import type { Identifier, Identity } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Collects and manages pretender mappings discovered during source file scanning.
|
|
4
|
+
* Acts as a registry where component-to-element relationships are added during
|
|
5
|
+
* traversal, then resolved into a flat list of pretenders with dependency linking.
|
|
6
|
+
*/
|
|
2
7
|
export declare class PretenderDirector {
|
|
3
8
|
#private;
|
|
9
|
+
/**
|
|
10
|
+
* Registers a component as a pretender mapping. If the identifier is already
|
|
11
|
+
* registered, the call is silently ignored (first definition wins).
|
|
12
|
+
*
|
|
13
|
+
* @param identifier - The component selector (e.g., component name)
|
|
14
|
+
* @param identity - The native HTML element the component renders as
|
|
15
|
+
* @param filePath - The relative file path where the component is defined
|
|
16
|
+
* @param line - The line number of the component declaration
|
|
17
|
+
* @param col - The column number of the component declaration
|
|
18
|
+
*/
|
|
4
19
|
add(identifier: Identifier, identity: Identity, filePath: string, line: number, col: number): void;
|
|
20
|
+
/**
|
|
21
|
+
* Resolves all registered mappings into a sorted array of Pretender objects.
|
|
22
|
+
* Follows component-to-component chains to determine the final native element identity.
|
|
23
|
+
*
|
|
24
|
+
* @returns A sorted array of resolved Pretender objects
|
|
25
|
+
*/
|
|
5
26
|
getPretenders(): import("packages/@markuplint/ml-config/lib/types.js").Pretender[];
|
|
6
27
|
}
|
|
@@ -5,16 +5,37 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
5
5
|
};
|
|
6
6
|
var _PretenderDirector_map;
|
|
7
7
|
import { dependencyMapper } from './dependency-mapper.js';
|
|
8
|
+
/**
|
|
9
|
+
* Collects and manages pretender mappings discovered during source file scanning.
|
|
10
|
+
* Acts as a registry where component-to-element relationships are added during
|
|
11
|
+
* traversal, then resolved into a flat list of pretenders with dependency linking.
|
|
12
|
+
*/
|
|
8
13
|
export class PretenderDirector {
|
|
9
14
|
constructor() {
|
|
10
15
|
_PretenderDirector_map.set(this, new Map());
|
|
11
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Registers a component as a pretender mapping. If the identifier is already
|
|
19
|
+
* registered, the call is silently ignored (first definition wins).
|
|
20
|
+
*
|
|
21
|
+
* @param identifier - The component selector (e.g., component name)
|
|
22
|
+
* @param identity - The native HTML element the component renders as
|
|
23
|
+
* @param filePath - The relative file path where the component is defined
|
|
24
|
+
* @param line - The line number of the component declaration
|
|
25
|
+
* @param col - The column number of the component declaration
|
|
26
|
+
*/
|
|
12
27
|
add(identifier, identity, filePath, line, col) {
|
|
13
28
|
if (__classPrivateFieldGet(this, _PretenderDirector_map, "f").has(identifier)) {
|
|
14
29
|
return;
|
|
15
30
|
}
|
|
16
31
|
__classPrivateFieldGet(this, _PretenderDirector_map, "f").set(identifier, [identity, `${filePath}:${line}:${col}`]);
|
|
17
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolves all registered mappings into a sorted array of Pretender objects.
|
|
35
|
+
* Follows component-to-component chains to determine the final native element identity.
|
|
36
|
+
*
|
|
37
|
+
* @returns A sorted array of resolved Pretender objects
|
|
38
|
+
*/
|
|
18
39
|
getPretenders() {
|
|
19
40
|
return dependencyMapper(__classPrivateFieldGet(this, _PretenderDirector_map, "f"));
|
|
20
41
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -1,15 +1,38 @@
|
|
|
1
1
|
import type { PretenderScanOptions, Pretender } from '@markuplint/ml-config';
|
|
2
|
+
/**
|
|
3
|
+
* A scan method function signature used by pretender scanners.
|
|
4
|
+
* Accepts a list of absolute file paths and optional scan options,
|
|
5
|
+
* and returns a promise resolving to an array of discovered pretender mappings.
|
|
6
|
+
*
|
|
7
|
+
* @template O - The scan options type, extending PretenderScanOptions
|
|
8
|
+
*/
|
|
2
9
|
export type PretenderScannerScanMethod<O extends PretenderScanOptions = PretenderScanOptions> =
|
|
3
10
|
/**
|
|
4
11
|
* @param files Absolute file paths. If it includes a relative path, throw an error.
|
|
5
|
-
* @param options
|
|
12
|
+
* @param options - Optional scan configuration
|
|
6
13
|
*/
|
|
7
14
|
(files: readonly string[], options?: Readonly<O>) => Promise<Pretender[]>;
|
|
15
|
+
/**
|
|
16
|
+
* The CSS selector string that identifies a component (e.g., the component name).
|
|
17
|
+
* Derived from the `selector` property of a Pretender.
|
|
18
|
+
*/
|
|
8
19
|
export type Identifier = Pretender['selector'];
|
|
20
|
+
/**
|
|
21
|
+
* The native HTML element identity that a component pretends to be.
|
|
22
|
+
* Can be a simple element name string or an object with detailed mapping.
|
|
23
|
+
* Derived from the `as` property of a Pretender.
|
|
24
|
+
*/
|
|
9
25
|
export type Identity = Pretender['as'];
|
|
26
|
+
/**
|
|
27
|
+
* Represents an attribute found on a JSX element during scanning.
|
|
28
|
+
*/
|
|
10
29
|
export type Attr = {
|
|
30
|
+
/** The kind of attribute: static string, boolean, dynamic expression, or spread */
|
|
11
31
|
readonly nodeType: 'static' | 'boolean' | 'dynamic' | 'spread';
|
|
32
|
+
/** The attribute name */
|
|
12
33
|
readonly name: string;
|
|
34
|
+
/** The attribute value (empty string for boolean, 'N/A' for spread) */
|
|
13
35
|
readonly value: string;
|
|
36
|
+
/** Optional type annotation for the attribute */
|
|
14
37
|
readonly type?: string;
|
|
15
38
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/pretenders",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.25",
|
|
4
4
|
"description": "It loads components and then creates the pretenders data from them.",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"clean": "tsc --build --clean tsconfig.build.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@markuplint/ml-config": "4.8.
|
|
29
|
-
"@markuplint/parser-utils": "4.8.
|
|
30
|
-
"glob": "
|
|
28
|
+
"@markuplint/ml-config": "4.8.15",
|
|
29
|
+
"@markuplint/parser-utils": "4.8.11",
|
|
30
|
+
"glob": "13.0.1",
|
|
31
31
|
"meow": "13.2.0",
|
|
32
|
-
"typescript": "5.9.
|
|
32
|
+
"typescript": "5.9.3"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "193ee7c1262bbed95424e38efdf1a8e56ff049f4"
|
|
35
35
|
}
|