wrec 0.36.1 → 0.36.3

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.
@@ -1,5 +1,3 @@
1
- declare type AnyClass = new (...args: any[]) => any;
2
-
3
1
  declare type ChangeCallback = (change: StateChange) => void;
4
2
 
5
3
  export declare function createElement(name: string, attributes: StringToString, innerHTML: string): HTMLElement;
@@ -19,12 +17,14 @@ declare type PropertyConfig<T = any> = {
19
17
  computed?: string;
20
18
  dispatch?: boolean;
21
19
  required?: boolean;
22
- type: AnyClass;
20
+ type: PropertyType;
23
21
  usedBy?: string | string[];
24
22
  value?: T;
25
23
  values?: T extends string ? string[] : never;
26
24
  };
27
25
 
26
+ declare type PropertyType = typeof Array | typeof Boolean | typeof HTMLElementBase | typeof Number | typeof Object | typeof String;
27
+
28
28
  declare type StateChange = {
29
29
  state: WrecState;
30
30
  statePath: string;
package/dist/wrec.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- declare type AnyClass = new (...args: any[]) => any;
2
-
3
1
  declare type ChangeCallback = (change: StateChange) => void;
4
2
 
5
3
  export declare function createElement(name: string, attributes: StringToString, innerHTML: string): HTMLElement;
@@ -19,12 +17,14 @@ declare type PropertyConfig<T = any> = {
19
17
  computed?: string;
20
18
  dispatch?: boolean;
21
19
  required?: boolean;
22
- type: AnyClass;
20
+ type: PropertyType;
23
21
  usedBy?: string | string[];
24
22
  value?: T;
25
23
  values?: T extends string ? string[] : never;
26
24
  };
27
25
 
26
+ declare type PropertyType = typeof Array | typeof Boolean | typeof HTMLElementBase | typeof Number | typeof Object | typeof String;
27
+
28
28
  declare type StateChange = {
29
29
  state: WrecState;
30
30
  statePath: string;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "wrec",
3
3
  "description": "a library that greatly simplifies building web components",
4
4
  "author": "R. Mark Volkmann",
5
- "version": "0.36.1",
5
+ "version": "0.36.3",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
@@ -41,7 +41,9 @@ function analyzeSourceFile(sourceFile) {
41
41
  if (!ts.isPropertyAssignment(property)) continue;
42
42
 
43
43
  const propName = getMemberName(property);
44
- if (!propName || !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propName)) continue;
44
+ if (!propName || !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propName)) {
45
+ continue;
46
+ }
45
47
 
46
48
  const declareType = getDeclareType(property.initializer);
47
49
  if (!declareType) continue;
package/scripts/lint.js CHANGED
@@ -122,6 +122,7 @@ const RESERVED_PROPERTY_NAMES = new Set(['class', 'style']);
122
122
  const SUPPORTED_PROPERTY_TYPE_NAMES = new Set([
123
123
  'Array',
124
124
  'Boolean',
125
+ 'HTMLElement',
125
126
  'Number',
126
127
  'Object',
127
128
  'String'
@@ -1101,6 +1102,12 @@ function getComponentPropertyMaps(filePath, sourceText, seen = new Set()) {
1101
1102
  return propertyMaps;
1102
1103
  }
1103
1104
 
1105
+ // Returns the constructed instance type for a constructor expression.
1106
+ function getConstructedType(checker, expression) {
1107
+ const constructorType = checker.getTypeAtLocation(expression);
1108
+ return constructorType.getConstructSignatures()[0]?.getReturnType();
1109
+ }
1110
+
1104
1111
  // Returns the referenced property name for a single `this.prop` binding.
1105
1112
  function getPropertyNameInAttribute(attrValue) {
1106
1113
  const match = attrValue.trim().match(PROPERTY_REF_RE);
@@ -1180,6 +1187,15 @@ function getPropertyConfigTypeName(typeName) {
1180
1187
  }
1181
1188
  }
1182
1189
 
1190
+ // Gets the base constructor name from a generic-looking type expression.
1191
+ function getPropertyTypeGenericBaseName(sourceFile, expression) {
1192
+ if (!expression) return undefined;
1193
+
1194
+ const text = expression.getText(sourceFile).trim();
1195
+ const match = text.match(/^([A-Za-z_$][\w$]*)\s*<[\s\S]+>$/);
1196
+ return match?.[1];
1197
+ }
1198
+
1183
1199
  // Derives a readable property type string from syntax or the type checker.
1184
1200
  function getPropertyTypeText(checker, sourceFile, expression) {
1185
1201
  const typeText = getTypeSyntaxText(sourceFile, expression);
@@ -1665,10 +1681,17 @@ function typeExpressionMatchesDeclaredType(
1665
1681
  declaredTypeNode
1666
1682
  ) {
1667
1683
  const declaredType = checker.getTypeFromTypeNode(declaredTypeNode);
1684
+ const typeKind = typeExpressionKind(typeExpression);
1668
1685
 
1669
- if (typeExpressionKind(typeExpression) === 'Object') {
1686
+ if (typeKind === 'Object') {
1670
1687
  return isNonArrayObjectLikeType(checker, declaredType);
1671
1688
  }
1689
+ if (typeKind === 'HTMLElement') {
1690
+ const elementType = getConstructedType(checker, typeExpression);
1691
+ return elementType
1692
+ ? checker.isTypeAssignableTo(elementType, declaredType)
1693
+ : false;
1694
+ }
1672
1695
 
1673
1696
  const runtimeType = checker.getTypeAtLocation(typeExpression);
1674
1697
  return checker.isTypeAssignableTo(runtimeType, declaredType);
@@ -1833,6 +1856,13 @@ function validateDefaultValue(checker, typeExpression, valueExpression) {
1833
1856
  }
1834
1857
  }
1835
1858
 
1859
+ if (typeKind === 'HTMLElement') {
1860
+ const elementType = getConstructedType(checker, typeExpression);
1861
+ if (!elementType || !checker.isTypeAssignableTo(valueType, elementType)) {
1862
+ return {typeName: 'HTMLElement', valueTypeName};
1863
+ }
1864
+ }
1865
+
1836
1866
  return undefined;
1837
1867
  }
1838
1868
 
@@ -1982,12 +2012,22 @@ function validatePropertyConfigs(
1982
2012
  findings.missingTypeProperties.push(
1983
2013
  `property "${propName}" does not specify a type`
1984
2014
  );
2015
+ } else if (
2016
+ SUPPORTED_PROPERTY_TYPE_NAMES.has(
2017
+ getPropertyTypeGenericBaseName(sourceFile, typeExpression)
2018
+ )
2019
+ ) {
2020
+ findings.invalidTypeProperties.push(
2021
+ `property "${propName}" type cannot use generic syntax like ` +
2022
+ `"${typeExpression.getText(sourceFile).trim()}"; use ` +
2023
+ `"${getPropertyTypeGenericBaseName(sourceFile, typeExpression)}" instead`
2024
+ );
1985
2025
  } else if (
1986
2026
  !SUPPORTED_PROPERTY_TYPE_NAMES.has(typeExpressionKind(typeExpression))
1987
2027
  ) {
1988
2028
  findings.invalidTypeProperties.push(
1989
2029
  `property "${propName}" type must be one of ` +
1990
- 'Boolean, Number, String, Object, or Array'
2030
+ 'Boolean, Number, String, Object, Array, or HTMLElement'
1991
2031
  );
1992
2032
  } else if (declaredTypeNode) {
1993
2033
  if (
File without changes