@cratis/scene.engine 4.22.1 → 4.24.0
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/descriptors/componentBadge.ts +41 -0
- package/descriptors/index.ts +7 -0
- package/descriptors/matchComponentQuery.ts +55 -0
- package/descriptors/rankFrequentlyUsedComponents.ts +29 -0
- package/descriptors/validateComponentDescriptors.ts +122 -0
- package/dist/cjs/descriptors/componentBadge.js +35 -0
- package/dist/cjs/descriptors/componentBadge.js.map +1 -0
- package/dist/cjs/descriptors/matchComponentQuery.js +56 -0
- package/dist/cjs/descriptors/matchComponentQuery.js.map +1 -0
- package/dist/cjs/descriptors/rankFrequentlyUsedComponents.js +18 -0
- package/dist/cjs/descriptors/rankFrequentlyUsedComponents.js.map +1 -0
- package/dist/cjs/descriptors/validateComponentDescriptors.js +116 -0
- package/dist/cjs/descriptors/validateComponentDescriptors.js.map +1 -0
- package/dist/cjs/index.js +13 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/structure/ApplicationStructureIndex.js +139 -0
- package/dist/cjs/structure/ApplicationStructureIndex.js.map +1 -0
- package/dist/cjs/structure/StructureDiagnosticCode.js +15 -0
- package/dist/cjs/structure/StructureDiagnosticCode.js.map +1 -0
- package/dist/esm/descriptors/componentBadge.d.ts +3 -0
- package/dist/esm/descriptors/componentBadge.d.ts.map +1 -0
- package/dist/esm/descriptors/componentBadge.js +33 -0
- package/dist/esm/descriptors/componentBadge.js.map +1 -0
- package/dist/esm/descriptors/index.d.ts +5 -0
- package/dist/esm/descriptors/index.d.ts.map +1 -0
- package/dist/esm/descriptors/index.js +5 -0
- package/dist/esm/descriptors/index.js.map +1 -0
- package/dist/esm/descriptors/matchComponentQuery.d.ts +9 -0
- package/dist/esm/descriptors/matchComponentQuery.d.ts.map +1 -0
- package/dist/esm/descriptors/matchComponentQuery.js +54 -0
- package/dist/esm/descriptors/matchComponentQuery.js.map +1 -0
- package/dist/esm/descriptors/rankFrequentlyUsedComponents.d.ts +7 -0
- package/dist/esm/descriptors/rankFrequentlyUsedComponents.d.ts.map +1 -0
- package/dist/esm/descriptors/rankFrequentlyUsedComponents.js +15 -0
- package/dist/esm/descriptors/rankFrequentlyUsedComponents.js.map +1 -0
- package/dist/esm/descriptors/validateComponentDescriptors.d.ts +3 -0
- package/dist/esm/descriptors/validateComponentDescriptors.d.ts.map +1 -0
- package/dist/esm/descriptors/validateComponentDescriptors.js +114 -0
- package/dist/esm/descriptors/validateComponentDescriptors.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/structure/ApplicationStructureIndex.d.ts +22 -0
- package/dist/esm/structure/ApplicationStructureIndex.d.ts.map +1 -0
- package/dist/esm/structure/ApplicationStructureIndex.js +137 -0
- package/dist/esm/structure/ApplicationStructureIndex.js.map +1 -0
- package/dist/esm/structure/StructureDiagnostic.d.ts +7 -0
- package/dist/esm/structure/StructureDiagnostic.d.ts.map +1 -0
- package/dist/esm/structure/StructureDiagnostic.js +2 -0
- package/dist/esm/structure/StructureDiagnostic.js.map +1 -0
- package/dist/esm/structure/StructureDiagnosticCode.d.ts +5 -0
- package/dist/esm/structure/StructureDiagnosticCode.d.ts.map +1 -0
- package/dist/esm/structure/StructureDiagnosticCode.js +13 -0
- package/dist/esm/structure/StructureDiagnosticCode.js.map +1 -0
- package/dist/esm/structure/index.d.ts +4 -0
- package/dist/esm/structure/index.d.ts.map +1 -0
- package/dist/esm/structure/index.js +4 -0
- package/dist/esm/structure/index.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/index.ts +2 -0
- package/package.json +3 -3
- package/structure/ApplicationStructureIndex.ts +163 -0
- package/structure/StructureDiagnostic.ts +18 -0
- package/structure/StructureDiagnosticCode.ts +14 -0
- package/structure/index.ts +6 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { ComponentDescriptor } from '@cratis/scene.model';
|
|
5
|
+
|
|
6
|
+
const vowels = 'aeiou';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The two-letter badge a component picker draws for a component that has no icon to show.
|
|
10
|
+
*
|
|
11
|
+
* An explicit `badge` wins (trimmed to two letters). Otherwise a name of several words (`Card grid`, `Stat card`) takes the
|
|
12
|
+
* initials of its first two words (`Cg`, `Sc`); a single word takes its first letter and the first consonant after it
|
|
13
|
+
* (`Button` -> `Bt`, `List` -> `Ls`), or its second letter when it has none. A camel-cased name is read as words
|
|
14
|
+
* (`dataTable` -> `Data table`). The first letter is upper case, the second lower case.
|
|
15
|
+
*/
|
|
16
|
+
export function componentBadge(descriptor: Pick<ComponentDescriptor, 'component' | 'displayName' | 'badge'>): string {
|
|
17
|
+
const explicit = descriptor.badge?.trim();
|
|
18
|
+
if (explicit) return capitalize(explicit.slice(0, 2));
|
|
19
|
+
|
|
20
|
+
const name = descriptor.displayName?.trim() || bareName(descriptor.component);
|
|
21
|
+
const words = name
|
|
22
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
23
|
+
.split(/[^A-Za-z0-9]+/)
|
|
24
|
+
.filter(word => word.length > 0);
|
|
25
|
+
|
|
26
|
+
if (words.length === 0) return '??';
|
|
27
|
+
if (words.length > 1) return capitalize(words[0][0] + words[1][0]);
|
|
28
|
+
|
|
29
|
+
const word = words[0];
|
|
30
|
+
if (word.length === 1) return word.toUpperCase();
|
|
31
|
+
const consonant = [...word.slice(1)].find(letter => /[a-z]/i.test(letter) && !vowels.includes(letter.toLowerCase()));
|
|
32
|
+
return capitalize(word[0] + (consonant ?? word[1]));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function bareName(component: string): string {
|
|
36
|
+
return component.slice(component.lastIndexOf(':') + 1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function capitalize(letters: string): string {
|
|
40
|
+
return letters.charAt(0).toUpperCase() + letters.slice(1).toLowerCase();
|
|
41
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
export * from './validateComponentDescriptors';
|
|
5
|
+
export * from './componentBadge';
|
|
6
|
+
export * from './matchComponentQuery';
|
|
7
|
+
export * from './rankFrequentlyUsedComponents';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { ComponentDescriptor } from '@cratis/scene.model';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* How a component answers a picker's filter text (spec PICK2).
|
|
8
|
+
*/
|
|
9
|
+
export interface ComponentQueryMatch {
|
|
10
|
+
/** The component is shown for this filter. */
|
|
11
|
+
matched: boolean;
|
|
12
|
+
|
|
13
|
+
/** What matched, strongest first: the display name, the category, or one of the keywords. Absent when nothing matched. */
|
|
14
|
+
via?: 'name' | 'category' | 'keyword';
|
|
15
|
+
|
|
16
|
+
/** The `[start, end)` ranges of the display name to highlight. Empty unless the name matched. */
|
|
17
|
+
ranges: [number, number][];
|
|
18
|
+
|
|
19
|
+
/** The keyword the component matched through. Present only when `via` is `keyword`: the picker shows it as a hint. */
|
|
20
|
+
keyword?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Decides whether a component is shown for the text typed in a picker's filter, and why.
|
|
25
|
+
*
|
|
26
|
+
* Matching is case-insensitive. The display name (or, when the descriptor has none, the bare component name) and the keywords match by
|
|
27
|
+
* substring. The category matches by the start of one of its words - `nav` finds every Navigation component, while `ta` does not find
|
|
28
|
+
* everything under `Data display`, which a substring match on the category would. A component is shown when any of the three
|
|
29
|
+
* match; it reports the first of name, category, keyword that did, so the picker highlights the name and shows a hint only when a
|
|
30
|
+
* keyword alone brought the component in. An empty filter matches everything and highlights nothing.
|
|
31
|
+
*/
|
|
32
|
+
export function matchComponentQuery(descriptor: Pick<ComponentDescriptor, 'component' | 'displayName' | 'category' | 'keywords'>, query: string): ComponentQueryMatch {
|
|
33
|
+
const needle = query.trim().toLowerCase();
|
|
34
|
+
if (needle.length === 0) return { matched: true, ranges: [] };
|
|
35
|
+
|
|
36
|
+
const name = descriptor.displayName ?? descriptor.component.slice(descriptor.component.lastIndexOf(':') + 1);
|
|
37
|
+
const ranges = occurrencesOf(name.toLowerCase(), needle);
|
|
38
|
+
if (ranges.length > 0) return { matched: true, via: 'name', ranges };
|
|
39
|
+
|
|
40
|
+
if (descriptor.category !== undefined && descriptor.category.toLowerCase().split(/\s+/).some(word => word.startsWith(needle))) {
|
|
41
|
+
return { matched: true, via: 'category', ranges: [] };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const keyword = (descriptor.keywords ?? []).find(candidate => candidate.toLowerCase().includes(needle));
|
|
45
|
+
return keyword === undefined ? { matched: false, ranges: [] } : { matched: true, via: 'keyword', ranges: [], keyword };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function occurrencesOf(text: string, needle: string): [number, number][] {
|
|
49
|
+
const found: [number, number][] = [];
|
|
50
|
+
for (let at = text.indexOf(needle); at >= 0; at = text.indexOf(needle, at + needle.length)) {
|
|
51
|
+
found.push([at, at + needle.length]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return found;
|
|
55
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* How often and how recently one component was added to a canvas.
|
|
6
|
+
*/
|
|
7
|
+
export interface ComponentUsage {
|
|
8
|
+
/** How many times the component was added. */
|
|
9
|
+
count: number;
|
|
10
|
+
|
|
11
|
+
/** When it was last added, in milliseconds since the epoch. */
|
|
12
|
+
last: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** The number of components the "Frequently used" group lists (spec PICK3). */
|
|
16
|
+
export const frequentlyUsedLimit = 6;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The components the "Frequently used" group lists: at most `limit` (6 by default), the most used first, ties broken by the most
|
|
20
|
+
* recent use, and any remaining tie by the component name so the order is stable. Components never used, or whose count is not a
|
|
21
|
+
* positive number, are not listed, so a picker hides the group when this is empty.
|
|
22
|
+
*/
|
|
23
|
+
export function rankFrequentlyUsedComponents(usage: Readonly<Record<string, ComponentUsage>>, limit: number = frequentlyUsedLimit): string[] {
|
|
24
|
+
return Object.entries(usage)
|
|
25
|
+
.filter(([, entry]) => Number.isFinite(entry.count) && entry.count > 0)
|
|
26
|
+
.sort(([leftName, left], [rightName, right]) => right.count - left.count || right.last - left.last || leftName.localeCompare(rightName))
|
|
27
|
+
.slice(0, Math.max(0, limit))
|
|
28
|
+
.map(([name]) => name);
|
|
29
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ComponentDescriptor, ComponentDesignModeDescriptor, DiagnosticCode, DiagnosticSeverity, PropertyDescriptor, PropertyEditorKind, PropertyValueType,
|
|
6
|
+
SceneDiagnostic, componentCategories,
|
|
7
|
+
} from '@cratis/scene.model';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Checks the component metadata a package ships - what a picker and a designer read without loading a component.
|
|
11
|
+
*
|
|
12
|
+
* - **CMP1** `componentCategoryMissing` (error): a registered component has no descriptor, or its descriptor declares no category.
|
|
13
|
+
* - `componentCategoryUnknown` (warning): the category is not one of the model's; a package may add its own, so this is a
|
|
14
|
+
* nudge towards the shared vocabulary, not a refusal.
|
|
15
|
+
* - `componentDesignModeInvalid` (error): the design-mode descriptor names an items or collection path that is not a `Collection`
|
|
16
|
+
* property of the component, or repeats an action id.
|
|
17
|
+
* - `propertyEditorOptionsInvalid` (error): an editor's parameters cannot work - a `reference` editor that does not say what it
|
|
18
|
+
* references, a step that is not positive, an empty list of slice kinds.
|
|
19
|
+
*
|
|
20
|
+
* `registered` is the bare or package-qualified names of the components the package registers; when given, each must be described.
|
|
21
|
+
* The result is in a stable order: registered components first (in the order given), then each descriptor's findings in its own order.
|
|
22
|
+
*/
|
|
23
|
+
export function validateComponentDescriptors(
|
|
24
|
+
descriptors: readonly ComponentDescriptor[],
|
|
25
|
+
registered?: readonly string[],
|
|
26
|
+
knownCategories: readonly string[] = componentCategories
|
|
27
|
+
): SceneDiagnostic[] {
|
|
28
|
+
const diagnostics: SceneDiagnostic[] = [];
|
|
29
|
+
const described = new Map(descriptors.map(descriptor => [descriptor.component, descriptor]));
|
|
30
|
+
|
|
31
|
+
for (const component of registered ?? []) {
|
|
32
|
+
if (!described.has(component)) {
|
|
33
|
+
diagnostics.push(missingCategory(component, `'${component}' is registered but has no descriptor, so it declares no category`));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const descriptor of descriptors) {
|
|
38
|
+
const { component } = descriptor;
|
|
39
|
+
|
|
40
|
+
if (descriptor.category === undefined || descriptor.category.trim().length === 0) {
|
|
41
|
+
diagnostics.push(missingCategory(component, `'${component}' declares no category`));
|
|
42
|
+
} else if (!knownCategories.includes(descriptor.category)) {
|
|
43
|
+
diagnostics.push({
|
|
44
|
+
code: DiagnosticCode.ComponentCategoryUnknown, severity: DiagnosticSeverity.Warning, component,
|
|
45
|
+
message: `'${component}' declares the category '${descriptor.category}', which is not one of ${knownCategories.join(', ')}`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (descriptor.designMode) {
|
|
50
|
+
diagnostics.push(...validateDesignMode(descriptor, descriptor.designMode));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
diagnostics.push(...validateEditorOptions(component, descriptor.properties, ''));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return diagnostics;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function missingCategory(component: string, message: string): SceneDiagnostic {
|
|
60
|
+
return { code: DiagnosticCode.ComponentCategoryMissing, severity: DiagnosticSeverity.Error, component, message };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function invalidDesignMode(component: string, message: string): SceneDiagnostic {
|
|
64
|
+
return { code: DiagnosticCode.ComponentDesignModeInvalid, severity: DiagnosticSeverity.Error, component, message };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function validateDesignMode(descriptor: ComponentDescriptor, designMode: ComponentDesignModeDescriptor): SceneDiagnostic[] {
|
|
68
|
+
const { component } = descriptor;
|
|
69
|
+
const diagnostics: SceneDiagnostic[] = [];
|
|
70
|
+
const collections = new Set(descriptor.properties.filter(property => property.valueType === PropertyValueType.Collection).map(property => property.path));
|
|
71
|
+
|
|
72
|
+
if (designMode.itemsPath !== undefined && !collections.has(designMode.itemsPath)) {
|
|
73
|
+
diagnostics.push(invalidDesignMode(component, `'${component}' names '${designMode.itemsPath}' as its design-mode items, which is not one of its Collection properties`));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const seenAdd = new Set<string>();
|
|
77
|
+
for (const action of designMode.addActions) {
|
|
78
|
+
if (seenAdd.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode add action '${action.id}' more than once`));
|
|
79
|
+
seenAdd.add(action.id);
|
|
80
|
+
|
|
81
|
+
if (action.collectionPath !== undefined && !collections.has(action.collectionPath)) {
|
|
82
|
+
diagnostics.push(invalidDesignMode(component, `the design-mode add action '${action.id}' of '${component}' adds to '${action.collectionPath}', which is not one of its Collection properties`));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const seenItem = new Set<string>();
|
|
87
|
+
for (const action of designMode.itemToolbar) {
|
|
88
|
+
if (seenItem.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode item action '${action.id}' more than once`));
|
|
89
|
+
seenItem.add(action.id);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return diagnostics;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function validateEditorOptions(component: string, properties: readonly PropertyDescriptor[], parent: string): SceneDiagnostic[] {
|
|
96
|
+
const diagnostics: SceneDiagnostic[] = [];
|
|
97
|
+
const invalid = (path: string, message: string): SceneDiagnostic => ({
|
|
98
|
+
code: DiagnosticCode.PropertyEditorOptionsInvalid, severity: DiagnosticSeverity.Error, component, path, message: `'${component}' property '${path}' ${message}`,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
for (const property of properties) {
|
|
102
|
+
const path = `${parent}${property.path}`;
|
|
103
|
+
const options = property.editorOptions;
|
|
104
|
+
|
|
105
|
+
if (property.editorKind === PropertyEditorKind.Reference && !options?.reference?.target) {
|
|
106
|
+
diagnostics.push(invalid(path, "uses the 'reference' editor without saying what it references (editorOptions.reference.target)"));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (options?.step !== undefined && !(options.step > 0)) {
|
|
110
|
+
diagnostics.push(invalid(path, 'declares a step that is not greater than zero'));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (options?.kinds !== undefined && options.kinds.length === 0) {
|
|
114
|
+
diagnostics.push(invalid(path, 'declares an empty list of kinds, which would offer nothing'));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (property.item) diagnostics.push(...validateEditorOptions(component, property.item.properties, `${path}[].`));
|
|
118
|
+
if (property.properties) diagnostics.push(...validateEditorOptions(component, property.properties, `${path}.`));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return diagnostics;
|
|
122
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
const vowels = 'aeiou';
|
|
6
|
+
/**
|
|
7
|
+
* The two-letter badge a component picker draws for a component that has no icon to show.
|
|
8
|
+
*
|
|
9
|
+
* An explicit `badge` wins (trimmed to two letters). Otherwise a name of several words (`Card grid`, `Stat card`) takes the
|
|
10
|
+
* initials of its first two words (`Cg`, `Sc`); a single word takes its first letter and the first consonant after it
|
|
11
|
+
* (`Button` -> `Bt`, `List` -> `Ls`), or its second letter when it has none. A camel-cased name is read as words
|
|
12
|
+
* (`dataTable` -> `Data table`). The first letter is upper case, the second lower case.
|
|
13
|
+
*/ function componentBadge(descriptor) {
|
|
14
|
+
const explicit = descriptor.badge?.trim();
|
|
15
|
+
if (explicit) return capitalize(explicit.slice(0, 2));
|
|
16
|
+
const name = descriptor.displayName?.trim() || bareName(descriptor.component);
|
|
17
|
+
const words = name.replace(/([a-z0-9])([A-Z])/g, '$1 $2').split(/[^A-Za-z0-9]+/).filter((word)=>word.length > 0);
|
|
18
|
+
if (words.length === 0) return '??';
|
|
19
|
+
if (words.length > 1) return capitalize(words[0][0] + words[1][0]);
|
|
20
|
+
const word = words[0];
|
|
21
|
+
if (word.length === 1) return word.toUpperCase();
|
|
22
|
+
const consonant = [
|
|
23
|
+
...word.slice(1)
|
|
24
|
+
].find((letter)=>/[a-z]/i.test(letter) && !vowels.includes(letter.toLowerCase()));
|
|
25
|
+
return capitalize(word[0] + (consonant ?? word[1]));
|
|
26
|
+
}
|
|
27
|
+
function bareName(component) {
|
|
28
|
+
return component.slice(component.lastIndexOf(':') + 1);
|
|
29
|
+
}
|
|
30
|
+
function capitalize(letters) {
|
|
31
|
+
return letters.charAt(0).toUpperCase() + letters.slice(1).toLowerCase();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exports.componentBadge = componentBadge;
|
|
35
|
+
//# sourceMappingURL=componentBadge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"componentBadge.js","sources":["../../../descriptors/componentBadge.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ComponentDescriptor } from '@cratis/scene.model';\n\nconst vowels = 'aeiou';\n\n/**\n * The two-letter badge a component picker draws for a component that has no icon to show.\n *\n * An explicit `badge` wins (trimmed to two letters). Otherwise a name of several words (`Card grid`, `Stat card`) takes the\n * initials of its first two words (`Cg`, `Sc`); a single word takes its first letter and the first consonant after it\n * (`Button` -> `Bt`, `List` -> `Ls`), or its second letter when it has none. A camel-cased name is read as words\n * (`dataTable` -> `Data table`). The first letter is upper case, the second lower case.\n */\nexport function componentBadge(descriptor: Pick<ComponentDescriptor, 'component' | 'displayName' | 'badge'>): string {\n const explicit = descriptor.badge?.trim();\n if (explicit) return capitalize(explicit.slice(0, 2));\n\n const name = descriptor.displayName?.trim() || bareName(descriptor.component);\n const words = name\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .split(/[^A-Za-z0-9]+/)\n .filter(word => word.length > 0);\n\n if (words.length === 0) return '??';\n if (words.length > 1) return capitalize(words[0][0] + words[1][0]);\n\n const word = words[0];\n if (word.length === 1) return word.toUpperCase();\n const consonant = [...word.slice(1)].find(letter => /[a-z]/i.test(letter) && !vowels.includes(letter.toLowerCase()));\n return capitalize(word[0] + (consonant ?? word[1]));\n}\n\nfunction bareName(component: string): string {\n return component.slice(component.lastIndexOf(':') + 1);\n}\n\nfunction capitalize(letters: string): string {\n return letters.charAt(0).toUpperCase() + letters.slice(1).toLowerCase();\n}\n"],"names":["vowels","componentBadge","descriptor","explicit","badge","trim","capitalize","slice","name","displayName","bareName","component","words","replace","split","filter","word","length","toUpperCase","consonant","find","letter","test","includes","toLowerCase","lastIndexOf","letters","charAt"],"mappings":";;AAAA;AACA;AAIA,MAAMA,MAAAA,GAAS,OAAA;AAEf;;;;;;;IAQO,SAASC,cAAAA,CAAeC,UAA4E,EAAA;IACvG,MAAMC,QAAAA,GAAWD,UAAAA,CAAWE,KAAK,EAAEC,IAAAA,EAAAA;AACnC,IAAA,IAAIF,UAAU,OAAOG,UAAAA,CAAWH,QAAAA,CAASI,KAAK,CAAC,CAAA,EAAG,CAAA,CAAA,CAAA;AAElD,IAAA,MAAMC,OAAON,UAAAA,CAAWO,WAAW,EAAEJ,IAAAA,EAAAA,IAAUK,QAAAA,CAASR,WAAWS,SAAS,CAAA;AAC5E,IAAA,MAAMC,KAAAA,GAAQJ,IAAAA,CACTK,OAAO,CAAC,sBAAsB,OAAA,CAAA,CAC9BC,KAAK,CAAC,eAAA,CAAA,CACNC,MAAM,CAACC,CAAAA,IAAAA,GAAQA,IAAAA,CAAKC,MAAM,GAAG,CAAA,CAAA;AAElC,IAAA,IAAIL,KAAAA,CAAMK,MAAM,KAAK,CAAA,EAAG,OAAO,IAAA;AAC/B,IAAA,IAAIL,MAAMK,MAAM,GAAG,CAAA,EAAG,OAAOX,WAAWM,KAAK,CAAC,CAAA,CAAE,CAAC,EAAE,GAAGA,KAAK,CAAC,CAAA,CAAE,CAAC,CAAA,CAAE,CAAA;IAEjE,MAAMI,IAAAA,GAAOJ,KAAK,CAAC,CAAA,CAAE;AACrB,IAAA,IAAII,KAAKC,MAAM,KAAK,CAAA,EAAG,OAAOD,KAAKE,WAAW,EAAA;AAC9C,IAAA,MAAMC,SAAAA,GAAY;AAAIH,QAAAA,GAAAA,IAAAA,CAAKT,KAAK,CAAC,CAAA;AAAG,KAAA,CAACa,IAAI,CAACC,CAAAA,MAAAA,GAAU,QAAA,CAASC,IAAI,CAACD,MAAAA,CAAAA,IAAW,CAACrB,MAAAA,CAAOuB,QAAQ,CAACF,OAAOG,WAAW,EAAA,CAAA,CAAA;IAChH,OAAOlB,UAAAA,CAAWU,IAAI,CAAC,CAAA,CAAE,IAAIG,SAAAA,IAAaH,IAAI,CAAC,CAAA,CAAE,CAAD,CAAA;AACpD;AAEA,SAASN,SAASC,SAAiB,EAAA;AAC/B,IAAA,OAAOA,UAAUJ,KAAK,CAACI,SAAAA,CAAUc,WAAW,CAAC,GAAA,CAAA,GAAO,CAAA,CAAA;AACxD;AAEA,SAASnB,WAAWoB,OAAe,EAAA;IAC/B,OAAOA,OAAAA,CAAQC,MAAM,CAAC,CAAA,CAAA,CAAGT,WAAW,KAAKQ,OAAAA,CAAQnB,KAAK,CAAC,CAAA,CAAA,CAAGiB,WAAW,EAAA;AACzE;;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
/**
|
|
6
|
+
* Decides whether a component is shown for the text typed in a picker's filter, and why.
|
|
7
|
+
*
|
|
8
|
+
* Matching is case-insensitive. The display name (or, when the descriptor has none, the bare component name) and the keywords match by
|
|
9
|
+
* substring. The category matches by the start of one of its words - `nav` finds every Navigation component, while `ta` does not find
|
|
10
|
+
* everything under `Data display`, which a substring match on the category would. A component is shown when any of the three
|
|
11
|
+
* match; it reports the first of name, category, keyword that did, so the picker highlights the name and shows a hint only when a
|
|
12
|
+
* keyword alone brought the component in. An empty filter matches everything and highlights nothing.
|
|
13
|
+
*/ function matchComponentQuery(descriptor, query) {
|
|
14
|
+
const needle = query.trim().toLowerCase();
|
|
15
|
+
if (needle.length === 0) return {
|
|
16
|
+
matched: true,
|
|
17
|
+
ranges: []
|
|
18
|
+
};
|
|
19
|
+
const name = descriptor.displayName ?? descriptor.component.slice(descriptor.component.lastIndexOf(':') + 1);
|
|
20
|
+
const ranges = occurrencesOf(name.toLowerCase(), needle);
|
|
21
|
+
if (ranges.length > 0) return {
|
|
22
|
+
matched: true,
|
|
23
|
+
via: 'name',
|
|
24
|
+
ranges
|
|
25
|
+
};
|
|
26
|
+
if (descriptor.category !== undefined && descriptor.category.toLowerCase().split(/\s+/).some((word)=>word.startsWith(needle))) {
|
|
27
|
+
return {
|
|
28
|
+
matched: true,
|
|
29
|
+
via: 'category',
|
|
30
|
+
ranges: []
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const keyword = (descriptor.keywords ?? []).find((candidate)=>candidate.toLowerCase().includes(needle));
|
|
34
|
+
return keyword === undefined ? {
|
|
35
|
+
matched: false,
|
|
36
|
+
ranges: []
|
|
37
|
+
} : {
|
|
38
|
+
matched: true,
|
|
39
|
+
via: 'keyword',
|
|
40
|
+
ranges: [],
|
|
41
|
+
keyword
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function occurrencesOf(text, needle) {
|
|
45
|
+
const found = [];
|
|
46
|
+
for(let at = text.indexOf(needle); at >= 0; at = text.indexOf(needle, at + needle.length)){
|
|
47
|
+
found.push([
|
|
48
|
+
at,
|
|
49
|
+
at + needle.length
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
return found;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
exports.matchComponentQuery = matchComponentQuery;
|
|
56
|
+
//# sourceMappingURL=matchComponentQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchComponentQuery.js","sources":["../../../descriptors/matchComponentQuery.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ComponentDescriptor } from '@cratis/scene.model';\n\n/**\n * How a component answers a picker's filter text (spec PICK2).\n */\nexport interface ComponentQueryMatch {\n /** The component is shown for this filter. */\n matched: boolean;\n\n /** What matched, strongest first: the display name, the category, or one of the keywords. Absent when nothing matched. */\n via?: 'name' | 'category' | 'keyword';\n\n /** The `[start, end)` ranges of the display name to highlight. Empty unless the name matched. */\n ranges: [number, number][];\n\n /** The keyword the component matched through. Present only when `via` is `keyword`: the picker shows it as a hint. */\n keyword?: string;\n}\n\n/**\n * Decides whether a component is shown for the text typed in a picker's filter, and why.\n *\n * Matching is case-insensitive. The display name (or, when the descriptor has none, the bare component name) and the keywords match by\n * substring. The category matches by the start of one of its words - `nav` finds every Navigation component, while `ta` does not find\n * everything under `Data display`, which a substring match on the category would. A component is shown when any of the three\n * match; it reports the first of name, category, keyword that did, so the picker highlights the name and shows a hint only when a\n * keyword alone brought the component in. An empty filter matches everything and highlights nothing.\n */\nexport function matchComponentQuery(descriptor: Pick<ComponentDescriptor, 'component' | 'displayName' | 'category' | 'keywords'>, query: string): ComponentQueryMatch {\n const needle = query.trim().toLowerCase();\n if (needle.length === 0) return { matched: true, ranges: [] };\n\n const name = descriptor.displayName ?? descriptor.component.slice(descriptor.component.lastIndexOf(':') + 1);\n const ranges = occurrencesOf(name.toLowerCase(), needle);\n if (ranges.length > 0) return { matched: true, via: 'name', ranges };\n\n if (descriptor.category !== undefined && descriptor.category.toLowerCase().split(/\\s+/).some(word => word.startsWith(needle))) {\n return { matched: true, via: 'category', ranges: [] };\n }\n\n const keyword = (descriptor.keywords ?? []).find(candidate => candidate.toLowerCase().includes(needle));\n return keyword === undefined ? { matched: false, ranges: [] } : { matched: true, via: 'keyword', ranges: [], keyword };\n}\n\nfunction occurrencesOf(text: string, needle: string): [number, number][] {\n const found: [number, number][] = [];\n for (let at = text.indexOf(needle); at >= 0; at = text.indexOf(needle, at + needle.length)) {\n found.push([at, at + needle.length]);\n }\n\n return found;\n}\n"],"names":["matchComponentQuery","descriptor","query","needle","trim","toLowerCase","length","matched","ranges","name","displayName","component","slice","lastIndexOf","occurrencesOf","via","category","undefined","split","some","word","startsWith","keyword","keywords","find","candidate","includes","text","found","at","indexOf","push"],"mappings":";;AAAA;AACA;AAqBA;;;;;;;;AAQC,IACM,SAASA,mBAAAA,CAAoBC,UAA4F,EAAEC,KAAa,EAAA;AAC3I,IAAA,MAAMC,MAAAA,GAASD,KAAAA,CAAME,IAAI,EAAA,CAAGC,WAAW,EAAA;AACvC,IAAA,IAAIF,MAAAA,CAAOG,MAAM,KAAK,CAAA,EAAG,OAAO;QAAEC,OAAAA,EAAS,IAAA;AAAMC,QAAAA,MAAAA,EAAQ;AAAG,KAAA;AAE5D,IAAA,MAAMC,IAAAA,GAAOR,UAAAA,CAAWS,WAAW,IAAIT,WAAWU,SAAS,CAACC,KAAK,CAACX,UAAAA,CAAWU,SAAS,CAACE,WAAW,CAAC,GAAA,CAAA,GAAO,CAAA,CAAA;AAC1G,IAAA,MAAML,MAAAA,GAASM,aAAAA,CAAcL,IAAAA,CAAKJ,WAAW,EAAA,EAAIF,MAAAA,CAAAA;AACjD,IAAA,IAAIK,MAAAA,CAAOF,MAAM,GAAG,CAAA,EAAG,OAAO;QAAEC,OAAAA,EAAS,IAAA;QAAMQ,GAAAA,EAAK,MAAA;AAAQP,QAAAA;AAAO,KAAA;AAEnE,IAAA,IAAIP,WAAWe,QAAQ,KAAKC,aAAahB,UAAAA,CAAWe,QAAQ,CAACX,WAAW,EAAA,CAAGa,KAAK,CAAC,KAAA,CAAA,CAAOC,IAAI,CAACC,CAAAA,OAAQA,IAAAA,CAAKC,UAAU,CAAClB,MAAAA,CAAAA,CAAAA,EAAU;QAC3H,OAAO;YAAEI,OAAAA,EAAS,IAAA;YAAMQ,GAAAA,EAAK,UAAA;AAAYP,YAAAA,MAAAA,EAAQ;AAAG,SAAA;AACxD,IAAA;AAEA,IAAA,MAAMc,UAAU,CAACrB,UAAAA,CAAWsB,QAAQ,IAAI,EAAC,EAAGC,IAAI,CAACC,CAAAA,SAAAA,GAAaA,UAAUpB,WAAW,EAAA,CAAGqB,QAAQ,CAACvB,MAAAA,CAAAA,CAAAA;AAC/F,IAAA,OAAOmB,YAAYL,SAAAA,GAAY;QAAEV,OAAAA,EAAS,KAAA;AAAOC,QAAAA,MAAAA,EAAQ;KAAG,GAAI;QAAED,OAAAA,EAAS,IAAA;QAAMQ,GAAAA,EAAK,SAAA;AAAWP,QAAAA,MAAAA,EAAQ,EAAE;AAAEc,QAAAA;AAAQ,KAAA;AACzH;AAEA,SAASR,aAAAA,CAAca,IAAY,EAAExB,MAAc,EAAA;AAC/C,IAAA,MAAMyB,QAA4B,EAAE;AACpC,IAAA,IAAK,IAAIC,EAAAA,GAAKF,IAAAA,CAAKG,OAAO,CAAC3B,SAAS0B,EAAAA,IAAM,CAAA,EAAGA,EAAAA,GAAKF,IAAAA,CAAKG,OAAO,CAAC3B,MAAAA,EAAQ0B,EAAAA,GAAK1B,MAAAA,CAAOG,MAAM,CAAA,CAAG;AACxFsB,QAAAA,KAAAA,CAAMG,IAAI,CAAC;AAACF,YAAAA,EAAAA;AAAIA,YAAAA,EAAAA,GAAK1B,OAAOG;AAAO,SAAA,CAAA;AACvC,IAAA;IAEA,OAAOsB,KAAAA;AACX;;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
/**
|
|
6
|
+
* How often and how recently one component was added to a canvas.
|
|
7
|
+
*/ /** The number of components the "Frequently used" group lists (spec PICK3). */ const frequentlyUsedLimit = 6;
|
|
8
|
+
/**
|
|
9
|
+
* The components the "Frequently used" group lists: at most `limit` (6 by default), the most used first, ties broken by the most
|
|
10
|
+
* recent use, and any remaining tie by the component name so the order is stable. Components never used, or whose count is not a
|
|
11
|
+
* positive number, are not listed, so a picker hides the group when this is empty.
|
|
12
|
+
*/ function rankFrequentlyUsedComponents(usage, limit = frequentlyUsedLimit) {
|
|
13
|
+
return Object.entries(usage).filter(([, entry])=>Number.isFinite(entry.count) && entry.count > 0).sort(([leftName, left], [rightName, right])=>right.count - left.count || right.last - left.last || leftName.localeCompare(rightName)).slice(0, Math.max(0, limit)).map(([name])=>name);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.frequentlyUsedLimit = frequentlyUsedLimit;
|
|
17
|
+
exports.rankFrequentlyUsedComponents = rankFrequentlyUsedComponents;
|
|
18
|
+
//# sourceMappingURL=rankFrequentlyUsedComponents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rankFrequentlyUsedComponents.js","sources":["../../../descriptors/rankFrequentlyUsedComponents.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * How often and how recently one component was added to a canvas.\n */\nexport interface ComponentUsage {\n /** How many times the component was added. */\n count: number;\n\n /** When it was last added, in milliseconds since the epoch. */\n last: number;\n}\n\n/** The number of components the \"Frequently used\" group lists (spec PICK3). */\nexport const frequentlyUsedLimit = 6;\n\n/**\n * The components the \"Frequently used\" group lists: at most `limit` (6 by default), the most used first, ties broken by the most\n * recent use, and any remaining tie by the component name so the order is stable. Components never used, or whose count is not a\n * positive number, are not listed, so a picker hides the group when this is empty.\n */\nexport function rankFrequentlyUsedComponents(usage: Readonly<Record<string, ComponentUsage>>, limit: number = frequentlyUsedLimit): string[] {\n return Object.entries(usage)\n .filter(([, entry]) => Number.isFinite(entry.count) && entry.count > 0)\n .sort(([leftName, left], [rightName, right]) => right.count - left.count || right.last - left.last || leftName.localeCompare(rightName))\n .slice(0, Math.max(0, limit))\n .map(([name]) => name);\n}\n"],"names":["frequentlyUsedLimit","rankFrequentlyUsedComponents","usage","limit","Object","entries","filter","entry","Number","isFinite","count","sort","leftName","left","rightName","right","last","localeCompare","slice","Math","max","map","name"],"mappings":";;AAAA;AACA;AAEA;;AAEC,oFAUM,MAAMA,sBAAsB;AAEnC;;;;AAIC,IACM,SAASC,4BAAAA,CAA6BC,KAA+C,EAAEC,QAAgBH,mBAAmB,EAAA;AAC7H,IAAA,OAAOI,MAAAA,CAAOC,OAAO,CAACH,KAAAA,CAAAA,CACjBI,MAAM,CAAC,CAAC,GAAGC,KAAAA,CAAM,GAAKC,MAAAA,CAAOC,QAAQ,CAACF,KAAAA,CAAMG,KAAK,CAAA,IAAKH,KAAAA,CAAMG,KAAK,GAAG,CAAA,CAAA,CACpEC,IAAI,CAAC,CAAC,CAACC,QAAAA,EAAUC,IAAAA,CAAK,EAAE,CAACC,SAAAA,EAAWC,KAAAA,CAAM,GAAKA,KAAAA,CAAML,KAAK,GAAGG,IAAAA,CAAKH,KAAK,IAAIK,KAAAA,CAAMC,IAAI,GAAGH,IAAAA,CAAKG,IAAI,IAAIJ,QAAAA,CAASK,aAAa,CAACH,SAAAA,CAAAA,CAAAA,CAC5HI,KAAK,CAAC,CAAA,EAAGC,IAAAA,CAAKC,GAAG,CAAC,CAAA,EAAGjB,KAAAA,CAAAA,CAAAA,CACrBkB,GAAG,CAAC,CAAC,CAACC,IAAAA,CAAK,GAAKA,IAAAA,CAAAA;AACzB;;;"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
|
|
5
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
6
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
7
|
+
/**
|
|
8
|
+
* Checks the component metadata a package ships - what a picker and a designer read without loading a component.
|
|
9
|
+
*
|
|
10
|
+
* - **CMP1** `componentCategoryMissing` (error): a registered component has no descriptor, or its descriptor declares no category.
|
|
11
|
+
* - `componentCategoryUnknown` (warning): the category is not one of the model's; a package may add its own, so this is a
|
|
12
|
+
* nudge towards the shared vocabulary, not a refusal.
|
|
13
|
+
* - `componentDesignModeInvalid` (error): the design-mode descriptor names an items or collection path that is not a `Collection`
|
|
14
|
+
* property of the component, or repeats an action id.
|
|
15
|
+
* - `propertyEditorOptionsInvalid` (error): an editor's parameters cannot work - a `reference` editor that does not say what it
|
|
16
|
+
* references, a step that is not positive, an empty list of slice kinds.
|
|
17
|
+
*
|
|
18
|
+
* `registered` is the bare or package-qualified names of the components the package registers; when given, each must be described.
|
|
19
|
+
* The result is in a stable order: registered components first (in the order given), then each descriptor's findings in its own order.
|
|
20
|
+
*/ function validateComponentDescriptors(descriptors, registered, knownCategories = scene_model.componentCategories) {
|
|
21
|
+
const diagnostics = [];
|
|
22
|
+
const described = new Map(descriptors.map((descriptor)=>[
|
|
23
|
+
descriptor.component,
|
|
24
|
+
descriptor
|
|
25
|
+
]));
|
|
26
|
+
for (const component of registered ?? []){
|
|
27
|
+
if (!described.has(component)) {
|
|
28
|
+
diagnostics.push(missingCategory(component, `'${component}' is registered but has no descriptor, so it declares no category`));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const descriptor of descriptors){
|
|
32
|
+
const { component } = descriptor;
|
|
33
|
+
if (descriptor.category === undefined || descriptor.category.trim().length === 0) {
|
|
34
|
+
diagnostics.push(missingCategory(component, `'${component}' declares no category`));
|
|
35
|
+
} else if (!knownCategories.includes(descriptor.category)) {
|
|
36
|
+
diagnostics.push({
|
|
37
|
+
code: scene_model.DiagnosticCode.ComponentCategoryUnknown,
|
|
38
|
+
severity: scene_model.DiagnosticSeverity.Warning,
|
|
39
|
+
component,
|
|
40
|
+
message: `'${component}' declares the category '${descriptor.category}', which is not one of ${knownCategories.join(', ')}`
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (descriptor.designMode) {
|
|
44
|
+
diagnostics.push(...validateDesignMode(descriptor, descriptor.designMode));
|
|
45
|
+
}
|
|
46
|
+
diagnostics.push(...validateEditorOptions(component, descriptor.properties, ''));
|
|
47
|
+
}
|
|
48
|
+
return diagnostics;
|
|
49
|
+
}
|
|
50
|
+
function missingCategory(component, message) {
|
|
51
|
+
return {
|
|
52
|
+
code: scene_model.DiagnosticCode.ComponentCategoryMissing,
|
|
53
|
+
severity: scene_model.DiagnosticSeverity.Error,
|
|
54
|
+
component,
|
|
55
|
+
message
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function invalidDesignMode(component, message) {
|
|
59
|
+
return {
|
|
60
|
+
code: scene_model.DiagnosticCode.ComponentDesignModeInvalid,
|
|
61
|
+
severity: scene_model.DiagnosticSeverity.Error,
|
|
62
|
+
component,
|
|
63
|
+
message
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function validateDesignMode(descriptor, designMode) {
|
|
67
|
+
const { component } = descriptor;
|
|
68
|
+
const diagnostics = [];
|
|
69
|
+
const collections = new Set(descriptor.properties.filter((property)=>property.valueType === scene_model.PropertyValueType.Collection).map((property)=>property.path));
|
|
70
|
+
if (designMode.itemsPath !== undefined && !collections.has(designMode.itemsPath)) {
|
|
71
|
+
diagnostics.push(invalidDesignMode(component, `'${component}' names '${designMode.itemsPath}' as its design-mode items, which is not one of its Collection properties`));
|
|
72
|
+
}
|
|
73
|
+
const seenAdd = new Set();
|
|
74
|
+
for (const action of designMode.addActions){
|
|
75
|
+
if (seenAdd.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode add action '${action.id}' more than once`));
|
|
76
|
+
seenAdd.add(action.id);
|
|
77
|
+
if (action.collectionPath !== undefined && !collections.has(action.collectionPath)) {
|
|
78
|
+
diagnostics.push(invalidDesignMode(component, `the design-mode add action '${action.id}' of '${component}' adds to '${action.collectionPath}', which is not one of its Collection properties`));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const seenItem = new Set();
|
|
82
|
+
for (const action of designMode.itemToolbar){
|
|
83
|
+
if (seenItem.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode item action '${action.id}' more than once`));
|
|
84
|
+
seenItem.add(action.id);
|
|
85
|
+
}
|
|
86
|
+
return diagnostics;
|
|
87
|
+
}
|
|
88
|
+
function validateEditorOptions(component, properties, parent) {
|
|
89
|
+
const diagnostics = [];
|
|
90
|
+
const invalid = (path, message)=>({
|
|
91
|
+
code: scene_model.DiagnosticCode.PropertyEditorOptionsInvalid,
|
|
92
|
+
severity: scene_model.DiagnosticSeverity.Error,
|
|
93
|
+
component,
|
|
94
|
+
path,
|
|
95
|
+
message: `'${component}' property '${path}' ${message}`
|
|
96
|
+
});
|
|
97
|
+
for (const property of properties){
|
|
98
|
+
const path = `${parent}${property.path}`;
|
|
99
|
+
const options = property.editorOptions;
|
|
100
|
+
if (property.editorKind === scene_model.PropertyEditorKind.Reference && !options?.reference?.target) {
|
|
101
|
+
diagnostics.push(invalid(path, "uses the 'reference' editor without saying what it references (editorOptions.reference.target)"));
|
|
102
|
+
}
|
|
103
|
+
if (options?.step !== undefined && !(options.step > 0)) {
|
|
104
|
+
diagnostics.push(invalid(path, 'declares a step that is not greater than zero'));
|
|
105
|
+
}
|
|
106
|
+
if (options?.kinds !== undefined && options.kinds.length === 0) {
|
|
107
|
+
diagnostics.push(invalid(path, 'declares an empty list of kinds, which would offer nothing'));
|
|
108
|
+
}
|
|
109
|
+
if (property.item) diagnostics.push(...validateEditorOptions(component, property.item.properties, `${path}[].`));
|
|
110
|
+
if (property.properties) diagnostics.push(...validateEditorOptions(component, property.properties, `${path}.`));
|
|
111
|
+
}
|
|
112
|
+
return diagnostics;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
exports.validateComponentDescriptors = validateComponentDescriptors;
|
|
116
|
+
//# sourceMappingURL=validateComponentDescriptors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateComponentDescriptors.js","sources":["../../../descriptors/validateComponentDescriptors.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport {\n ComponentDescriptor, ComponentDesignModeDescriptor, DiagnosticCode, DiagnosticSeverity, PropertyDescriptor, PropertyEditorKind, PropertyValueType,\n SceneDiagnostic, componentCategories,\n} from '@cratis/scene.model';\n\n/**\n * Checks the component metadata a package ships - what a picker and a designer read without loading a component.\n *\n * - **CMP1** `componentCategoryMissing` (error): a registered component has no descriptor, or its descriptor declares no category.\n * - `componentCategoryUnknown` (warning): the category is not one of the model's; a package may add its own, so this is a\n * nudge towards the shared vocabulary, not a refusal.\n * - `componentDesignModeInvalid` (error): the design-mode descriptor names an items or collection path that is not a `Collection`\n * property of the component, or repeats an action id.\n * - `propertyEditorOptionsInvalid` (error): an editor's parameters cannot work - a `reference` editor that does not say what it\n * references, a step that is not positive, an empty list of slice kinds.\n *\n * `registered` is the bare or package-qualified names of the components the package registers; when given, each must be described.\n * The result is in a stable order: registered components first (in the order given), then each descriptor's findings in its own order.\n */\nexport function validateComponentDescriptors(\n descriptors: readonly ComponentDescriptor[],\n registered?: readonly string[],\n knownCategories: readonly string[] = componentCategories\n): SceneDiagnostic[] {\n const diagnostics: SceneDiagnostic[] = [];\n const described = new Map(descriptors.map(descriptor => [descriptor.component, descriptor]));\n\n for (const component of registered ?? []) {\n if (!described.has(component)) {\n diagnostics.push(missingCategory(component, `'${component}' is registered but has no descriptor, so it declares no category`));\n }\n }\n\n for (const descriptor of descriptors) {\n const { component } = descriptor;\n\n if (descriptor.category === undefined || descriptor.category.trim().length === 0) {\n diagnostics.push(missingCategory(component, `'${component}' declares no category`));\n } else if (!knownCategories.includes(descriptor.category)) {\n diagnostics.push({\n code: DiagnosticCode.ComponentCategoryUnknown, severity: DiagnosticSeverity.Warning, component,\n message: `'${component}' declares the category '${descriptor.category}', which is not one of ${knownCategories.join(', ')}`,\n });\n }\n\n if (descriptor.designMode) {\n diagnostics.push(...validateDesignMode(descriptor, descriptor.designMode));\n }\n\n diagnostics.push(...validateEditorOptions(component, descriptor.properties, ''));\n }\n\n return diagnostics;\n}\n\nfunction missingCategory(component: string, message: string): SceneDiagnostic {\n return { code: DiagnosticCode.ComponentCategoryMissing, severity: DiagnosticSeverity.Error, component, message };\n}\n\nfunction invalidDesignMode(component: string, message: string): SceneDiagnostic {\n return { code: DiagnosticCode.ComponentDesignModeInvalid, severity: DiagnosticSeverity.Error, component, message };\n}\n\nfunction validateDesignMode(descriptor: ComponentDescriptor, designMode: ComponentDesignModeDescriptor): SceneDiagnostic[] {\n const { component } = descriptor;\n const diagnostics: SceneDiagnostic[] = [];\n const collections = new Set(descriptor.properties.filter(property => property.valueType === PropertyValueType.Collection).map(property => property.path));\n\n if (designMode.itemsPath !== undefined && !collections.has(designMode.itemsPath)) {\n diagnostics.push(invalidDesignMode(component, `'${component}' names '${designMode.itemsPath}' as its design-mode items, which is not one of its Collection properties`));\n }\n\n const seenAdd = new Set<string>();\n for (const action of designMode.addActions) {\n if (seenAdd.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode add action '${action.id}' more than once`));\n seenAdd.add(action.id);\n\n if (action.collectionPath !== undefined && !collections.has(action.collectionPath)) {\n diagnostics.push(invalidDesignMode(component, `the design-mode add action '${action.id}' of '${component}' adds to '${action.collectionPath}', which is not one of its Collection properties`));\n }\n }\n\n const seenItem = new Set<string>();\n for (const action of designMode.itemToolbar) {\n if (seenItem.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode item action '${action.id}' more than once`));\n seenItem.add(action.id);\n }\n\n return diagnostics;\n}\n\nfunction validateEditorOptions(component: string, properties: readonly PropertyDescriptor[], parent: string): SceneDiagnostic[] {\n const diagnostics: SceneDiagnostic[] = [];\n const invalid = (path: string, message: string): SceneDiagnostic => ({\n code: DiagnosticCode.PropertyEditorOptionsInvalid, severity: DiagnosticSeverity.Error, component, path, message: `'${component}' property '${path}' ${message}`,\n });\n\n for (const property of properties) {\n const path = `${parent}${property.path}`;\n const options = property.editorOptions;\n\n if (property.editorKind === PropertyEditorKind.Reference && !options?.reference?.target) {\n diagnostics.push(invalid(path, \"uses the 'reference' editor without saying what it references (editorOptions.reference.target)\"));\n }\n\n if (options?.step !== undefined && !(options.step > 0)) {\n diagnostics.push(invalid(path, 'declares a step that is not greater than zero'));\n }\n\n if (options?.kinds !== undefined && options.kinds.length === 0) {\n diagnostics.push(invalid(path, 'declares an empty list of kinds, which would offer nothing'));\n }\n\n if (property.item) diagnostics.push(...validateEditorOptions(component, property.item.properties, `${path}[].`));\n if (property.properties) diagnostics.push(...validateEditorOptions(component, property.properties, `${path}.`));\n }\n\n return diagnostics;\n}\n"],"names":["validateComponentDescriptors","descriptors","registered","knownCategories","componentCategories","diagnostics","described","Map","map","descriptor","component","has","push","missingCategory","category","undefined","trim","length","includes","code","DiagnosticCode","ComponentCategoryUnknown","severity","DiagnosticSeverity","Warning","message","join","designMode","validateDesignMode","validateEditorOptions","properties","ComponentCategoryMissing","Error","invalidDesignMode","ComponentDesignModeInvalid","collections","Set","filter","property","valueType","PropertyValueType","Collection","path","itemsPath","seenAdd","action","addActions","id","add","collectionPath","seenItem","itemToolbar","parent","invalid","PropertyEditorOptionsInvalid","options","editorOptions","editorKind","PropertyEditorKind","Reference","reference","target","step","kinds","item"],"mappings":"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"}
|
package/dist/cjs/index.js
CHANGED
|
@@ -27,6 +27,10 @@ var resolveIconLibraries = require('./icons/resolveIconLibraries.js');
|
|
|
27
27
|
var EffectiveIconEntry = require('./icons/EffectiveIconEntry.js');
|
|
28
28
|
var EffectiveIconCatalog = require('./icons/EffectiveIconCatalog.js');
|
|
29
29
|
var analyzeIconImpact = require('./icons/analyzeIconImpact.js');
|
|
30
|
+
var validateComponentDescriptors = require('./descriptors/validateComponentDescriptors.js');
|
|
31
|
+
var componentBadge = require('./descriptors/componentBadge.js');
|
|
32
|
+
var matchComponentQuery = require('./descriptors/matchComponentQuery.js');
|
|
33
|
+
var rankFrequentlyUsedComponents = require('./descriptors/rankFrequentlyUsedComponents.js');
|
|
30
34
|
var resolveComponentName = require('./resolveComponentName.js');
|
|
31
35
|
var computeSizeClass = require('./computeSizeClass.js');
|
|
32
36
|
var evaluateFlowArrangement = require('./evaluateFlowArrangement.js');
|
|
@@ -71,6 +75,8 @@ var applyEdit = require('./editing/applyEdit.js');
|
|
|
71
75
|
var iconDiagnostics = require('./editing/iconDiagnostics.js');
|
|
72
76
|
var diagnoseIcons = require('./editing/diagnoseIcons.js');
|
|
73
77
|
var collectIconUsages = require('./editing/collectIconUsages.js');
|
|
78
|
+
var StructureDiagnosticCode = require('./structure/StructureDiagnosticCode.js');
|
|
79
|
+
var ApplicationStructureIndex = require('./structure/ApplicationStructureIndex.js');
|
|
74
80
|
|
|
75
81
|
|
|
76
82
|
|
|
@@ -115,6 +121,11 @@ exports.resolveIconLibraries = resolveIconLibraries.resolveIconLibraries;
|
|
|
115
121
|
exports.referencesOfEntry = EffectiveIconEntry.referencesOfEntry;
|
|
116
122
|
exports.EffectiveIconCatalog = EffectiveIconCatalog.EffectiveIconCatalog;
|
|
117
123
|
exports.analyzeIconImpact = analyzeIconImpact.analyzeIconImpact;
|
|
124
|
+
exports.validateComponentDescriptors = validateComponentDescriptors.validateComponentDescriptors;
|
|
125
|
+
exports.componentBadge = componentBadge.componentBadge;
|
|
126
|
+
exports.matchComponentQuery = matchComponentQuery.matchComponentQuery;
|
|
127
|
+
exports.frequentlyUsedLimit = rankFrequentlyUsedComponents.frequentlyUsedLimit;
|
|
128
|
+
exports.rankFrequentlyUsedComponents = rankFrequentlyUsedComponents.rankFrequentlyUsedComponents;
|
|
118
129
|
exports.corePackage = resolveComponentName.corePackage;
|
|
119
130
|
exports.effectivePackages = resolveComponentName.effectivePackages;
|
|
120
131
|
exports.resolveComponentName = resolveComponentName.resolveComponentName;
|
|
@@ -209,4 +220,6 @@ exports.iconProblemsOfItems = iconDiagnostics.iconProblemsOfItems;
|
|
|
209
220
|
exports.iconProblemsOfProperty = iconDiagnostics.iconProblemsOfProperty;
|
|
210
221
|
exports.diagnoseIcons = diagnoseIcons.diagnoseIcons;
|
|
211
222
|
exports.collectIconUsages = collectIconUsages.collectIconUsages;
|
|
223
|
+
exports.StructureDiagnosticCode = StructureDiagnosticCode.StructureDiagnosticCode;
|
|
224
|
+
exports.ApplicationStructureIndex = ApplicationStructureIndex.ApplicationStructureIndex;
|
|
212
225
|
//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|