Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
dist/
.DS_Store
.idea/

## Rocket ignore files
docs/_merged_data/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ class MyEl extends HTMLElement {
prop5;

/** @type {boolean} */
set setter() {}
set setter(value) {}
get setter() {}

set getter2(){}
set getter2(value){}
/** @type {string} */
get getter2(){}

Expand Down
2 changes: 1 addition & 1 deletion packages/analyzer/fixtures/01-class/03-jsdoc/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"declarations": [
{
"kind": "class",
"description": "https://a.b\n[CD]https://e.f\ng|HIJ\nklmEn? Oh Pee",
"description": "https://a.b\r\n[CD]https://e.f\r\ng|HIJ\r\nklmEn? Oh Pee",
"name": "MyElement",
"cssProperties": [
{
Expand Down
4 changes: 2 additions & 2 deletions packages/analyzer/fixtures/07-plugin-lit/01-basic/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@
"text": "boolean"
},
"default": "false",
"description": "this description never gets picked up by the analyzer. \nso we lose some info about default values and the fact it is both property and attribute",
"description": "this description never gets picked up by the analyzer. \r\nso we lose some info about default values and the fact it is both property and attribute",
"attribute": "disabled"
}
],
Expand All @@ -216,7 +216,7 @@
"text": "boolean"
},
"default": "false",
"description": "this description never gets picked up by the analyzer. \nso we lose some info about default values and the fact it is both property and attribute",
"description": "this description never gets picked up by the analyzer. \r\nso we lose some info about default values and the fact it is both property and attribute",
"fieldName": "disabled"
}
],
Expand Down
88 changes: 47 additions & 41 deletions packages/analyzer/src/utils/find-external-manifests.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from 'fs';
import path from 'path';
import { findDependencies, splitPath } from '@custom-elements-manifest/find-dependencies';
import fs from 'fs'
import path from 'path'
import { findDependencies, splitPath } from '@custom-elements-manifest/find-dependencies'

/**
* @typedef {import('custom-elements-manifest/schema').Package} Package
Expand All @@ -13,55 +13,61 @@ import { findDependencies, splitPath } from '@custom-elements-manifest/find-depe
* basePath?: string,
* }} [options]
*/
export async function findExternalManifests(paths, {basePath = process.cwd(), nodeModulesDepth}) {
export async function findExternalManifests (paths, { basePath = process.cwd(), nodeModulesDepth }) {
/** @type {Package[]} */
const cemsToMerge = [];
const visited = new Set();
const cemsToMerge = []
const visited = new Set()
try {

const dependencies = await findDependencies(paths, {basePath, nodeModulesDepth});

dependencies?.forEach((dependencyPath) => {
const isCurrentPackageRegex = new RegExp(`^${basePath}\\${path.sep}(?!.*node_modules).*`);
if (isCurrentPackageRegex.test(dependencyPath)) {
// Make sure that we do not look for custom-elements.json in our own package
return;
}
const dependencies = await findDependencies(paths, { basePath, nodeModulesDepth })

const { packageRoot, packageName } = splitPath(dependencyPath);
dependencies?.forEach((dependencyPath) => {
const isCurrentPackageRegex = new RegExp(`^${basePath}\\${path.sep}(?!.*node_modules).*`)
if (isCurrentPackageRegex.test(dependencyPath)) {
// Make sure that we do not look for custom-elements.json in our own package
return
}

const { packageRoot, packageName } = splitPath(dependencyPath)

if(visited.has(packageName)) return;
visited.add(packageName);
if (visited.has(packageName)) return
visited.add(packageName)

const packageJsonPath = `${packageRoot}${path.sep}package.json`;
const cemPath = `${packageRoot}${path.sep}custom-elements.json`;
const packageJsonPath = `${packageRoot}${path.sep}package.json`
const cemPath = `${packageRoot}${path.sep}custom-elements.json`

/** Try to find `custom-elements.json` at `node_modules/specifier/custom-elements.json` */
if(fs.existsSync(cemPath)) {
try {
const cem = JSON.parse(fs.readFileSync(cemPath).toString());
cemsToMerge.push(cem);
return;
} catch(e) {
throw new Error(`Failed to read custom-elements.json at path "${cemPath}". \n\n${e.stack}`);
/** Try to find `custom-elements.json` at `node_modules/specifier/custom-elements.json` */
if (fs.existsSync(cemPath)) {
try {
const cem = JSON.parse(fs.readFileSync(cemPath).toString())
cemsToMerge.push(cem)
return
} catch (e) {
throw new Error(`Failed to read custom-elements.json at path "${cemPath}". \n\n${e.stack}`)
}
}
}

/** See if the `package.json` has a `customElements` field or if it has listed `./customElements` in its export map */
if(fs.existsSync(packageJsonPath)) {
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString());
const cemLocation = packageJson?.customElements || packageJson?.exports?.['./customElements'];
/** See if the `package.json` has a `customElements` field or if it has listed `./customElements` in its export map */
if (fs.existsSync(packageJsonPath)) {
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString())
const cemLocation = packageJson?.customElements || packageJson?.exports?.['./customElements']

if(cemLocation) {
try {
const cemPath = path.resolve(packageRoot, cemLocation);
const cem = JSON.parse(fs.readFileSync(cemPath).toString());
cemsToMerge.push(cem);
} catch(e) {
throw new Error(`Failed to read custom-elements.json at path "${cemPath}". \n\n${e.stack}`);
if (cemLocation) {
try {
const cemPath = path.resolve(packageRoot, cemLocation)
const cem = JSON.parse(fs.readFileSync(cemPath).toString())
cemsToMerge.push(cem)
} catch (e) {
throw new Error(`Failed to read custom-elements.json at path "${cemPath}". \n\n${e.stack}`)
}
}
}
}
});
})

return cemsToMerge;
return cemsToMerge
} catch (e) {
console.trace(e)
throw new Error(`Failed to find external manifests. \n\n${e.stack}`)
}
}
37 changes: 37 additions & 0 deletions packages/find-dependencies/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,43 @@ Will output:
]
```

## TypeScript Support

This package provides full TypeScript support including:

### Path Mapping
Automatically resolves TypeScript path mapping from `tsconfig.json`:

```json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@utils/*": ["src/utils/*"],
"@components/*": ["src/components/*"],
"snake_case/*": ["src/my_utilities/*"],
"lib2024/*": ["src/ui_components/*"],
"domain.types/*": ["src/core_types/*"]
}
}
}
```

### Flexible Alias Patterns
Supports various alias naming conventions:
- **Standard**: `@utils/*`, `@components/*`
- **Snake case**: `snake_case/*`, `my_utils/*`
- **Numeric**: `lib2024/*`, `v2/*`
- **Domain-style**: `domain.types/*`, `app.config/*`
- **Cryptic**: `u/*`, `c/*`

### Import Types
Handles all TypeScript import/export variants:
- `import type { Type } from './module.js'`
- `export type { Type } from './module.js'`
- `import('./module.js')` (dynamic imports)
- Mixed JavaScript/TypeScript projects

## Configuration

```ts
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Use TypeScript path mapping import
import type { ComponentConfig } from '@/types/config.js'

export class BaseComponent {
protected config: ComponentConfig

constructor(config: ComponentConfig) {
this.config = config
}

public getName(): string {
return this.config.name
}

public isEnabled(): boolean {
return this.config.enabled
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { MyElement } from './src/MyElement.js'
export type * from './src/types.js'
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { MyElementElement } from './types.js'
import { BaseComponent } from '@components/base/BaseComponent.js'
import { validation } from '@utils/validation.js'

declare global {
interface HTMLElementTagNameMap {
'my-element': MyElement;
}
}

export class MyElement extends BaseComponent {
private value: string = ''

constructor() {
super({
name: 'my-element',
version: '1.0.0',
enabled: true
})
}

setValue(newValue: string): void {
if (validation(newValue)) {
this.value = newValue
}
}

getValue(): string {
return this.value
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface MyElementElement extends HTMLElement {
small: boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { SecondElement } from './src/SecondElement.js'
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Test relative and absolute path imports with TypeScript path mapping
import { MyElement } from '../../my-element/index.js'
import { API_URL } from '@shared/config.js'
import type { EventHandlers } from '@shared/types.js'

export class SecondElement extends HTMLElement {
private handlers: EventHandlers = {}
private myElement: MyElement

constructor() {
super()
console.log('API URL:', API_URL)
this.myElement = new MyElement()
}

setHandlers(handlers: EventHandlers): void {
this.handlers = handlers
}

getHandlers(): EventHandlers {
return this.handlers
}

getMyElement(): MyElement {
return this.myElement
}
}
18 changes: 18 additions & 0 deletions packages/find-dependencies/fixtures/regular-ts/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Entry point with various import types
import { MyElement } from './components/my-element/index.js'
import { SecondElement } from './components/second-element/index.js'
import { utility } from './utils/helper.js'
import { sharedConstant } from './shared/constants.js'

// TypeScript path mapping imports
import { validation } from '@utils/validation.js'
import { BaseComponent } from '@components/base/BaseComponent.js'
import { API_URL } from '@shared/config.js'

// Type-only imports (now should work with TypeScript parser!)
import type { ComponentConfig } from './types/config.js'
import type { EventHandlers } from '@shared/types.js'

export { MyElement, SecondElement }
export { utility, sharedConstant, validation, BaseComponent, API_URL }
export type { ComponentConfig, EventHandlers }
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { sharedConstant } from './constants.js'

export const API_URL = `https://api.example.com/${sharedConstant}`

export const ENDPOINTS = {
users: '/users',
posts: '/posts'
} as const
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const sharedConstant = 'SHARED_VALUE'

export const APP_NAME = 'TypeScript Test App'

export const VERSION = '1.0.0'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface EventHandlers {
onClick?: (event: Event) => void
onFocus?: (event: FocusEvent) => void
onInput?: (event: InputEvent) => void
}

export type ComponentState = 'idle' | 'loading' | 'success' | 'error'
10 changes: 10 additions & 0 deletions packages/find-dependencies/fixtures/regular-ts/src/types/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface ComponentConfig {
name: string
version: string
enabled: boolean
}

export interface ElementOptions {
tagName: string
shadow: boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function utility(value: string): string {
return `Processed: ${value}`
}

export function formatDate(date: Date): string {
return date.toISOString()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { formatDate } from './helper.js'

export function validation(input: string): boolean {
if (!input || input.trim().length === 0) {
return false
}

// Use relative import to test dependency resolution
formatDate(new Date())

return input.length > 3
}
19 changes: 19 additions & 0 deletions packages/find-dependencies/fixtures/regular-ts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"outDir": "dist",
"declaration": true,
"declarationDir": "dist-types",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"],
"@shared/*": ["src/shared/*"]
},
"types": []
},
"include": ["src/**/*"]
}
Loading
Loading