glass-easel 0.1.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/README.md +40 -0
- package/dist/glass_easel.all.d.ts +1 -0
- package/dist/glass_easel.all.js +2 -0
- package/dist/glass_easel.all.js.map +1 -0
- package/dist/glass_easel.domlike.global.d.ts +1 -0
- package/dist/glass_easel.domlike.global.js +2 -0
- package/dist/glass_easel.domlike.global.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/types/src/backend/backend_protocol.d.ts +119 -0
- package/dist/types/src/backend/backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/composed_backend_protocol.d.ts +90 -0
- package/dist/types/src/backend/composed_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/domlike_backend_protocol.d.ts +76 -0
- package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/mode.d.ts +46 -0
- package/dist/types/src/backend/mode.d.ts.map +1 -0
- package/dist/types/src/backend/suggested_backend_protocol.d.ts +30 -0
- package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/behavior.d.ts +428 -0
- package/dist/types/src/behavior.d.ts.map +1 -0
- package/dist/types/src/class_list.d.ts +79 -0
- package/dist/types/src/class_list.d.ts.map +1 -0
- package/dist/types/src/component.d.ts +291 -0
- package/dist/types/src/component.d.ts.map +1 -0
- package/dist/types/src/component_params.d.ts +239 -0
- package/dist/types/src/component_params.d.ts.map +1 -0
- package/dist/types/src/component_space.d.ts +164 -0
- package/dist/types/src/component_space.d.ts.map +1 -0
- package/dist/types/src/data_path.d.ts +5 -0
- package/dist/types/src/data_path.d.ts.map +1 -0
- package/dist/types/src/data_proxy.d.ts +107 -0
- package/dist/types/src/data_proxy.d.ts.map +1 -0
- package/dist/types/src/data_utils.d.ts +3 -0
- package/dist/types/src/data_utils.d.ts.map +1 -0
- package/dist/types/src/element.d.ts +275 -0
- package/dist/types/src/element.d.ts.map +1 -0
- package/dist/types/src/element_iterator.d.ts +43 -0
- package/dist/types/src/element_iterator.d.ts.map +1 -0
- package/dist/types/src/event.d.ts +104 -0
- package/dist/types/src/event.d.ts.map +1 -0
- package/dist/types/src/external_shadow_tree.d.ts +20 -0
- package/dist/types/src/external_shadow_tree.d.ts.map +1 -0
- package/dist/types/src/func_arr.d.ts +39 -0
- package/dist/types/src/func_arr.d.ts.map +1 -0
- package/dist/types/src/global_options.d.ts +111 -0
- package/dist/types/src/global_options.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +43 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/mutation_observer.d.ts +79 -0
- package/dist/types/src/mutation_observer.d.ts.map +1 -0
- package/dist/types/src/native_node.d.ts +8 -0
- package/dist/types/src/native_node.d.ts.map +1 -0
- package/dist/types/src/node.d.ts +49 -0
- package/dist/types/src/node.d.ts.map +1 -0
- package/dist/types/src/relation.d.ts +47 -0
- package/dist/types/src/relation.d.ts.map +1 -0
- package/dist/types/src/render.d.ts +3 -0
- package/dist/types/src/render.d.ts.map +1 -0
- package/dist/types/src/selector.d.ts +32 -0
- package/dist/types/src/selector.d.ts.map +1 -0
- package/dist/types/src/shadow_root.d.ts +136 -0
- package/dist/types/src/shadow_root.d.ts.map +1 -0
- package/dist/types/src/template_engine.d.ts +18 -0
- package/dist/types/src/template_engine.d.ts.map +1 -0
- package/dist/types/src/text_node.d.ts +32 -0
- package/dist/types/src/text_node.d.ts.map +1 -0
- package/dist/types/src/tmpl/index.d.ts +18 -0
- package/dist/types/src/tmpl/index.d.ts.map +1 -0
- package/dist/types/src/tmpl/native_rendering.d.ts +45 -0
- package/dist/types/src/tmpl/native_rendering.d.ts.map +1 -0
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +80 -0
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +1 -0
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +50 -0
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +1 -0
- package/dist/types/src/tmpl/range_list_diff.d.ts +19 -0
- package/dist/types/src/tmpl/range_list_diff.d.ts.map +1 -0
- package/dist/types/src/trait_behaviors.d.ts +38 -0
- package/dist/types/src/trait_behaviors.d.ts.map +1 -0
- package/dist/types/src/virtual_node.d.ts +10 -0
- package/dist/types/src/virtual_node.d.ts.map +1 -0
- package/dist/types/tests/backend/domlike.test.d.ts +2 -0
- package/dist/types/tests/backend/domlike.test.d.ts.map +1 -0
- package/dist/types/tests/base/env.d.ts +29 -0
- package/dist/types/tests/base/env.d.ts.map +1 -0
- package/dist/types/tests/base/match.d.ts +9 -0
- package/dist/types/tests/base/match.d.ts.map +1 -0
- package/dist/types/tests/core/backend.test.d.ts +2 -0
- package/dist/types/tests/core/backend.test.d.ts.map +1 -0
- package/dist/types/tests/core/behavior.test.d.ts +2 -0
- package/dist/types/tests/core/behavior.test.d.ts.map +1 -0
- package/dist/types/tests/core/component_space.test.d.ts +2 -0
- package/dist/types/tests/core/component_space.test.d.ts.map +1 -0
- package/dist/types/tests/core/data_update.test.d.ts +2 -0
- package/dist/types/tests/core/data_update.test.d.ts.map +1 -0
- package/dist/types/tests/core/misc.test.d.ts +2 -0
- package/dist/types/tests/core/misc.test.d.ts.map +1 -0
- package/dist/types/tests/core/placeholder.test.d.ts +2 -0
- package/dist/types/tests/core/placeholder.test.d.ts.map +1 -0
- package/dist/types/tests/core/slot.test.d.ts +2 -0
- package/dist/types/tests/core/slot.test.d.ts.map +1 -0
- package/dist/types/tests/core/trait_behaviors.test.d.ts +2 -0
- package/dist/types/tests/core/trait_behaviors.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/binding_map.test.d.ts +2 -0
- package/dist/types/tests/tmpl/binding_map.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/event.test.d.ts +2 -0
- package/dist/types/tests/tmpl/event.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/expression.test.d.ts +2 -0
- package/dist/types/tests/tmpl/expression.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/lvalue.test.d.ts +2 -0
- package/dist/types/tests/tmpl/lvalue.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/native_rendering.test.d.ts +2 -0
- package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/structure.test.d.ts +2 -0
- package/dist/types/tests/tmpl/structure.test.d.ts.map +1 -0
- package/dist/types/tests/types/chaining.test.d.ts +2 -0
- package/dist/types/tests/types/chaining.test.d.ts.map +1 -0
- package/dist/types/tests/types/createElement.test.d.ts +2 -0
- package/dist/types/tests/types/createElement.test.d.ts.map +1 -0
- package/dist/types/tests/types/definition.test.d.ts +2 -0
- package/dist/types/tests/types/definition.test.d.ts.map +1 -0
- package/guide/zh_CN/advanced/binding_map_update.md +32 -0
- package/guide/zh_CN/advanced/build_args.md +28 -0
- package/guide/zh_CN/advanced/component_filter.md +70 -0
- package/guide/zh_CN/advanced/component_space.md +124 -0
- package/guide/zh_CN/advanced/custom_backend.md +53 -0
- package/guide/zh_CN/advanced/error_listener.md +32 -0
- package/guide/zh_CN/advanced/external_component.md +73 -0
- package/guide/zh_CN/advanced/template_engine.md +61 -0
- package/guide/zh_CN/appendix/backend_protocol.md +501 -0
- package/guide/zh_CN/appendix/list_diff_algorithm.md +406 -0
- package/guide/zh_CN/basic/beginning.md +94 -0
- package/guide/zh_CN/basic/component.md +156 -0
- package/guide/zh_CN/basic/event.md +169 -0
- package/guide/zh_CN/basic/lifetime.md +66 -0
- package/guide/zh_CN/basic/method.md +62 -0
- package/guide/zh_CN/basic/template.md +135 -0
- package/guide/zh_CN/data_management/advanced_update.md +170 -0
- package/guide/zh_CN/data_management/data_deep_copy.md +157 -0
- package/guide/zh_CN/data_management/data_observer.md +154 -0
- package/guide/zh_CN/data_management/property_early_init.md +31 -0
- package/guide/zh_CN/data_management/pure_data_pattern.md +21 -0
- package/guide/zh_CN/index.md +93 -0
- package/guide/zh_CN/interaction/behavior.md +52 -0
- package/guide/zh_CN/interaction/component_path.md +37 -0
- package/guide/zh_CN/interaction/generic.md +73 -0
- package/guide/zh_CN/interaction/placeholder.md +40 -0
- package/guide/zh_CN/interaction/relation.md +151 -0
- package/guide/zh_CN/interaction/slot.md +137 -0
- package/guide/zh_CN/interaction/template_import.md +94 -0
- package/guide/zh_CN/interaction/trait_behavior.md +117 -0
- package/guide/zh_CN/styling/external_class.md +46 -0
- package/guide/zh_CN/styling/style_isolation.md +54 -0
- package/guide/zh_CN/styling/virtual_host.md +52 -0
- package/guide/zh_CN/tree/element_iterator.md +54 -0
- package/guide/zh_CN/tree/mutation_observer.md +52 -0
- package/guide/zh_CN/tree/node_tree.md +142 -0
- package/guide/zh_CN/tree/node_tree_modification.md +78 -0
- package/guide/zh_CN/tree/selector.md +66 -0
- package/jest.config.js +6 -0
- package/jest.dts.config.js +9 -0
- package/jest.unit.config.js +14 -0
- package/package.json +28 -0
- package/src/backend/backend_protocol.ts +313 -0
- package/src/backend/composed_backend_protocol.ts +252 -0
- package/src/backend/domlike_backend_protocol.ts +370 -0
- package/src/backend/mode.ts +51 -0
- package/src/backend/suggested_backend_protocol.ts +83 -0
- package/src/behavior.ts +1655 -0
- package/src/bootstrap_dom_dev.js +22 -0
- package/src/class_list.ts +376 -0
- package/src/component.ts +1309 -0
- package/src/component_params.ts +461 -0
- package/src/component_space.ts +547 -0
- package/src/data_path.ts +225 -0
- package/src/data_proxy.ts +670 -0
- package/src/data_utils.ts +50 -0
- package/src/element.ts +1966 -0
- package/src/element_iterator.ts +158 -0
- package/src/event.ts +401 -0
- package/src/external_shadow_tree.ts +27 -0
- package/src/func_arr.ts +198 -0
- package/src/global_options.ts +242 -0
- package/src/index.ts +187 -0
- package/src/mutation_observer.ts +252 -0
- package/src/native_node.ts +74 -0
- package/src/node.ts +174 -0
- package/src/relation.ts +380 -0
- package/src/render.ts +25 -0
- package/src/selector.ts +218 -0
- package/src/shadow_root.ts +766 -0
- package/src/template_engine.ts +45 -0
- package/src/text_node.ts +149 -0
- package/src/tmpl/index.ts +199 -0
- package/src/tmpl/native_rendering.ts +175 -0
- package/src/tmpl/proc_gen_wrapper.ts +954 -0
- package/src/tmpl/proc_gen_wrapper_dom.ts +230 -0
- package/src/tmpl/range_list_diff.ts +443 -0
- package/src/trait_behaviors.ts +51 -0
- package/src/virtual_node.ts +51 -0
- package/tests/backend/domlike.test.ts +254 -0
- package/tests/base/env.ts +78 -0
- package/tests/base/match.ts +185 -0
- package/tests/core/backend.test.ts +144 -0
- package/tests/core/behavior.test.ts +546 -0
- package/tests/core/component_space.test.ts +212 -0
- package/tests/core/data_update.test.ts +461 -0
- package/tests/core/misc.test.ts +339 -0
- package/tests/core/placeholder.test.ts +180 -0
- package/tests/core/slot.test.ts +1495 -0
- package/tests/core/trait_behaviors.test.ts +153 -0
- package/tests/legacy/README.md +3 -0
- package/tests/legacy/behavior.test.js +293 -0
- package/tests/legacy/component.test.js +1247 -0
- package/tests/legacy/data_path.test.js +149 -0
- package/tests/legacy/data_proxy.test.js +759 -0
- package/tests/legacy/element_iterator.test.js +148 -0
- package/tests/legacy/event.test.js +849 -0
- package/tests/legacy/external.test.js +510 -0
- package/tests/legacy/extra_info.test.js +109 -0
- package/tests/legacy/generics.test.js +176 -0
- package/tests/legacy/mutation_observer.test.js +210 -0
- package/tests/legacy/relation.test.js +517 -0
- package/tests/legacy/selector.test.js +263 -0
- package/tests/legacy/slot.test.js +915 -0
- package/tests/legacy/virtual.test.js +394 -0
- package/tests/tmpl/binding_map.test.ts +208 -0
- package/tests/tmpl/event.test.ts +206 -0
- package/tests/tmpl/expression.test.ts +429 -0
- package/tests/tmpl/lvalue.test.ts +160 -0
- package/tests/tmpl/native_rendering.test.ts +155 -0
- package/tests/tmpl/structure.test.ts +998 -0
- package/tests/types/chaining.test.ts +614 -0
- package/tests/types/createElement.test.ts +82 -0
- package/tests/types/definition.test.ts +442 -0
- package/tsconfig.json +11 -0
- package/webpack.config.js +270 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ComponentParams,
|
|
3
|
+
DataList,
|
|
4
|
+
PropertyList,
|
|
5
|
+
MethodList,
|
|
6
|
+
ComponentInstance,
|
|
7
|
+
Empty,
|
|
8
|
+
} from './component_params'
|
|
9
|
+
import {
|
|
10
|
+
Behavior,
|
|
11
|
+
BehaviorBuilder,
|
|
12
|
+
GeneralBehavior,
|
|
13
|
+
} from './behavior'
|
|
14
|
+
import {
|
|
15
|
+
ComponentDefinition,
|
|
16
|
+
GeneralComponentDefinition,
|
|
17
|
+
Component,
|
|
18
|
+
GeneralComponent,
|
|
19
|
+
} from './component'
|
|
20
|
+
import {
|
|
21
|
+
ComponentOptions,
|
|
22
|
+
normalizeComponentOptions,
|
|
23
|
+
NormalizedComponentOptions,
|
|
24
|
+
} from './global_options'
|
|
25
|
+
import {
|
|
26
|
+
StyleScopeManager,
|
|
27
|
+
} from './class_list'
|
|
28
|
+
import {
|
|
29
|
+
GeneralBackendContext,
|
|
30
|
+
} from '.'
|
|
31
|
+
import { TraitBehavior } from './trait_behaviors'
|
|
32
|
+
|
|
33
|
+
const normalizePath = (path: string, basePath: string): string => {
|
|
34
|
+
let slices: string[]
|
|
35
|
+
if (path[0] !== '/') {
|
|
36
|
+
slices = basePath.split('/').slice(0, -1).concat(path.split('/'))
|
|
37
|
+
} else {
|
|
38
|
+
slices = path.split('/')
|
|
39
|
+
}
|
|
40
|
+
const finalSlices = [] as string[]
|
|
41
|
+
for (let i = 0; i < slices.length; i += 1) {
|
|
42
|
+
const slice = slices[i]!
|
|
43
|
+
if (slice === '' || slice === '.') continue
|
|
44
|
+
if (slice === '..') {
|
|
45
|
+
finalSlices.pop()
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
finalSlices.push(slice)
|
|
49
|
+
}
|
|
50
|
+
return finalSlices.join('/')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const normalizeUrl = (
|
|
54
|
+
path: string,
|
|
55
|
+
relPath: string,
|
|
56
|
+
): { domain: string | null, absPath: string } => {
|
|
57
|
+
const protoSep = path.indexOf('://')
|
|
58
|
+
if (protoSep > 0) {
|
|
59
|
+
const domainSep = path.indexOf('/', protoSep + 3)
|
|
60
|
+
if (domainSep > 0) {
|
|
61
|
+
const domain = path.slice(0, domainSep)
|
|
62
|
+
const absPath = normalizePath(path.slice(domainSep + 1), '')
|
|
63
|
+
return {
|
|
64
|
+
domain,
|
|
65
|
+
absPath,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// HACK for invalid URL like `a://the-comp` , provide some compatibility
|
|
69
|
+
const domain = path.slice(0, protoSep + 3)
|
|
70
|
+
const absPath = normalizePath(path.slice(protoSep + 3), '')
|
|
71
|
+
return {
|
|
72
|
+
domain,
|
|
73
|
+
absPath,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
domain: null,
|
|
78
|
+
absPath: normalizePath(path, relPath),
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export class ComponentWaitingList {
|
|
83
|
+
/** @internal */
|
|
84
|
+
private _$callbacks: ((c: GeneralComponentDefinition) => void)[] = []
|
|
85
|
+
|
|
86
|
+
add(callback: (c: GeneralComponentDefinition) => void) {
|
|
87
|
+
this._$callbacks.push(callback)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
remove(callback: (c: GeneralComponentDefinition) => void) {
|
|
91
|
+
const index = this._$callbacks.indexOf(callback)
|
|
92
|
+
// must gurrantee order here (cannot swap-remove)
|
|
93
|
+
this._$callbacks.splice(index, 1)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
call(c: GeneralComponentDefinition) {
|
|
97
|
+
const cbs = this._$callbacks
|
|
98
|
+
this._$callbacks = []
|
|
99
|
+
for (let i = 0; i < cbs.length; i += 1) {
|
|
100
|
+
const f = cbs[i]!
|
|
101
|
+
f(c)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** A group of components for cross-component using */
|
|
107
|
+
export class ComponentSpace {
|
|
108
|
+
/** @internal */
|
|
109
|
+
private _$behaviorList = Object.create(null) as { [path: string]: GeneralBehavior }
|
|
110
|
+
/** @internal */
|
|
111
|
+
private _$pubBehaviorList = Object.create(null) as { [path: string]: GeneralBehavior }
|
|
112
|
+
/** @internal */
|
|
113
|
+
private _$list = Object.create(null) as { [path: string]: GeneralComponentDefinition }
|
|
114
|
+
/** @internal */
|
|
115
|
+
private _$pubList = Object.create(null) as { [path: string]: GeneralComponentDefinition }
|
|
116
|
+
/** @internal */
|
|
117
|
+
private _$importedSpaces = Object.create(null) as {
|
|
118
|
+
[path: string]: {
|
|
119
|
+
space: ComponentSpace,
|
|
120
|
+
privateUse: boolean,
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** @internal */
|
|
124
|
+
private _$defaultComponent: string
|
|
125
|
+
/** @internal */
|
|
126
|
+
private _$componentOptions: NormalizedComponentOptions
|
|
127
|
+
styleScopeManager: StyleScopeManager
|
|
128
|
+
/** @internal */
|
|
129
|
+
private _$listWaiting = Object.create(null) as {
|
|
130
|
+
[path: string]: ComponentWaitingList
|
|
131
|
+
}
|
|
132
|
+
/** @internal */
|
|
133
|
+
private _$pubListWaiting = Object.create(null) as {
|
|
134
|
+
[path: string]: ComponentWaitingList
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Create a new component space
|
|
139
|
+
*
|
|
140
|
+
* The `defaultComponent` is the default component path.
|
|
141
|
+
* It should be defined soon after creation.
|
|
142
|
+
* A `baseSpace` can be provided as a "base" component space -
|
|
143
|
+
* every component alias (and behavior alias) in the space will be imported when creation.
|
|
144
|
+
* However, if any new component is added to the base space after the creation,
|
|
145
|
+
* it will not be added to the created space.
|
|
146
|
+
*/
|
|
147
|
+
constructor(
|
|
148
|
+
defaultComponent?: string,
|
|
149
|
+
baseSpace?: ComponentSpace,
|
|
150
|
+
styleScopeManager?: StyleScopeManager,
|
|
151
|
+
) {
|
|
152
|
+
if (baseSpace) {
|
|
153
|
+
Object.assign(this._$list, baseSpace._$pubList)
|
|
154
|
+
Object.assign(this._$behaviorList, baseSpace._$pubBehaviorList)
|
|
155
|
+
}
|
|
156
|
+
this._$defaultComponent = defaultComponent ?? ''
|
|
157
|
+
this._$componentOptions = normalizeComponentOptions({}, baseSpace?._$componentOptions)
|
|
158
|
+
this.styleScopeManager = styleScopeManager || new StyleScopeManager()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Update the default component options for this space
|
|
163
|
+
*
|
|
164
|
+
* The new options will be merged with existing options.
|
|
165
|
+
*/
|
|
166
|
+
updateComponentOptions(componentOptions: ComponentOptions) {
|
|
167
|
+
this._$componentOptions = normalizeComponentOptions(componentOptions, this._$componentOptions)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
getComponentOptions(): NormalizedComponentOptions {
|
|
171
|
+
return this._$componentOptions
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Update the base component space
|
|
176
|
+
*
|
|
177
|
+
* This will add the components in `baseSpace` if there is no components with the same names.
|
|
178
|
+
*/
|
|
179
|
+
updateBaseSpace(baseSpace: ComponentSpace) {
|
|
180
|
+
this._$list = Object.assign(
|
|
181
|
+
Object.create(null) as { [path: string]: GeneralComponentDefinition },
|
|
182
|
+
baseSpace._$pubList,
|
|
183
|
+
this._$list,
|
|
184
|
+
)
|
|
185
|
+
this._$behaviorList = Object.assign(
|
|
186
|
+
Object.create(null) as { [path: string]: GeneralBehavior },
|
|
187
|
+
baseSpace._$pubBehaviorList,
|
|
188
|
+
this._$behaviorList,
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Import another component space
|
|
194
|
+
*
|
|
195
|
+
* The components in the imported space can be used by components in this space.
|
|
196
|
+
* The `protoDomain` should be URL-like, i.e. `space://another-space` .
|
|
197
|
+
* When using, the components in the imported space should be specified with `protoDomain` .
|
|
198
|
+
* For example, if `protoDomain` is `space://another-space` and one imported component has alias `my-comp` ,
|
|
199
|
+
* then it should be specified with `space://another-space/my-comp` .
|
|
200
|
+
* If `privateUse` set to false, only component alias in the imported space can be used;
|
|
201
|
+
* the original name of components is imported otherwise.
|
|
202
|
+
*/
|
|
203
|
+
importSpace(
|
|
204
|
+
protoDomain: string,
|
|
205
|
+
space: ComponentSpace,
|
|
206
|
+
privateUse: boolean,
|
|
207
|
+
) {
|
|
208
|
+
this._$importedSpaces[protoDomain] = {
|
|
209
|
+
space,
|
|
210
|
+
privateUse,
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Get a component by the `path`
|
|
216
|
+
*
|
|
217
|
+
* The component `is` is actually treated as the "path" of the component.
|
|
218
|
+
* In other words, the component `is` field can be a string like `path/to/the/component` .
|
|
219
|
+
* Other components can be used by the component with "relative path" spacified.
|
|
220
|
+
* In this method, if the `path` is given as a relative path (not started with `/` ),
|
|
221
|
+
* it will be converted according to the `basePath` .
|
|
222
|
+
* If the `path` is given as a URL-like format,
|
|
223
|
+
* the component will be searched in imported comopnent spaces ( `importSpace()` for details).
|
|
224
|
+
*/
|
|
225
|
+
getComponentByUrl(path: string, basePath: string): GeneralComponentDefinition {
|
|
226
|
+
const { domain, absPath } = normalizeUrl(path, basePath)
|
|
227
|
+
const comp = this.getComponent(absPath, true, domain)
|
|
228
|
+
if (!comp) {
|
|
229
|
+
throw new Error(`There is no component "${absPath}" in the space and no default component can be used`)
|
|
230
|
+
}
|
|
231
|
+
return comp
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get a component by the `path`
|
|
236
|
+
*
|
|
237
|
+
* Similar to `getComponentByUrl()` ,
|
|
238
|
+
* but returns `null` instead of the default component if no compnent was found.
|
|
239
|
+
*/
|
|
240
|
+
getComponentByUrlWithoutDefault(
|
|
241
|
+
path: string,
|
|
242
|
+
relPath: string,
|
|
243
|
+
): GeneralComponentDefinition | null {
|
|
244
|
+
const { domain, absPath } = normalizeUrl(path, relPath)
|
|
245
|
+
const comp = this.getComponent(absPath, false, domain)
|
|
246
|
+
return comp || null
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private getComponent(
|
|
250
|
+
absPath: string,
|
|
251
|
+
withDefault = true,
|
|
252
|
+
domain: string | null = null,
|
|
253
|
+
): GeneralComponentDefinition | undefined {
|
|
254
|
+
let list: { [is: string]: GeneralComponentDefinition } | undefined
|
|
255
|
+
if (domain) {
|
|
256
|
+
const target = this._$importedSpaces[domain]
|
|
257
|
+
if (target) {
|
|
258
|
+
const { space, privateUse } = target
|
|
259
|
+
if (privateUse) {
|
|
260
|
+
list = space._$list
|
|
261
|
+
} else {
|
|
262
|
+
list = space._$pubList
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} else {
|
|
266
|
+
list = this._$list
|
|
267
|
+
}
|
|
268
|
+
if (list) {
|
|
269
|
+
const def = list[absPath]
|
|
270
|
+
if (def) return def
|
|
271
|
+
}
|
|
272
|
+
if (withDefault) {
|
|
273
|
+
return this._$list[this._$defaultComponent]
|
|
274
|
+
}
|
|
275
|
+
return undefined
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
getDefaultComponent(): GeneralComponentDefinition | null {
|
|
279
|
+
return this._$list[this._$defaultComponent] || null
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
isDefaultComponent(def: GeneralComponentDefinition) {
|
|
283
|
+
return this._$list[this._$defaultComponent] === def
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get a behavior by the `path`
|
|
288
|
+
*
|
|
289
|
+
* Similar to `getComponentByUrlWithoutDefault()` but for behaviors.
|
|
290
|
+
*/
|
|
291
|
+
getBehaviorByUrl(path: string, relPath: string): GeneralBehavior | null {
|
|
292
|
+
const { domain, absPath } = normalizeUrl(path, relPath)
|
|
293
|
+
return this._$getBehavior(absPath, domain) || null
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** @internal */
|
|
297
|
+
_$getBehavior(
|
|
298
|
+
absPath: string,
|
|
299
|
+
domain: string | null = null,
|
|
300
|
+
): GeneralBehavior | undefined {
|
|
301
|
+
let list: { [is: string]: GeneralBehavior } | undefined
|
|
302
|
+
if (domain) {
|
|
303
|
+
const target = this._$importedSpaces[domain]
|
|
304
|
+
if (target) {
|
|
305
|
+
const { space, privateUse } = target
|
|
306
|
+
if (privateUse) {
|
|
307
|
+
list = space._$behaviorList
|
|
308
|
+
} else {
|
|
309
|
+
list = space._$pubBehaviorList
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
list = this._$behaviorList
|
|
314
|
+
}
|
|
315
|
+
if (list) {
|
|
316
|
+
const def = list[absPath]
|
|
317
|
+
if (def) return def
|
|
318
|
+
}
|
|
319
|
+
return undefined
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/** Register a component in this space */
|
|
323
|
+
defineComponent<
|
|
324
|
+
TData extends DataList,
|
|
325
|
+
TProperty extends PropertyList,
|
|
326
|
+
TMethod extends MethodList,
|
|
327
|
+
>(
|
|
328
|
+
def: ComponentParams<TData, TProperty, TMethod> &
|
|
329
|
+
ThisType<ComponentInstance<TData, TProperty, TMethod>>,
|
|
330
|
+
): ComponentDefinition<TData, TProperty, TMethod> {
|
|
331
|
+
const is = def.is
|
|
332
|
+
const ret = new BehaviorBuilder(is, this).definition(def).registerComponent()
|
|
333
|
+
return ret
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Register a behavior in this space */
|
|
337
|
+
defineBehavior<
|
|
338
|
+
TData extends DataList,
|
|
339
|
+
TProperty extends PropertyList,
|
|
340
|
+
TMethod extends MethodList,
|
|
341
|
+
>(
|
|
342
|
+
def: ComponentParams<TData, TProperty, TMethod> &
|
|
343
|
+
ThisType<ComponentInstance<TData, TProperty, TMethod>>,
|
|
344
|
+
): Behavior<TData, TProperty, TMethod, never> {
|
|
345
|
+
const is = def.is
|
|
346
|
+
const ret = new BehaviorBuilder(is, this).definition(def).registerBehavior()
|
|
347
|
+
return ret
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** Register a component or a behavior with chaining API */
|
|
351
|
+
define(is?: string): BehaviorBuilder {
|
|
352
|
+
return new BehaviorBuilder(is, this)
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Register a component or a behavior with chaining API (with method caller type specified)
|
|
357
|
+
*
|
|
358
|
+
* This API is generally designed for adapters which require special method callers.
|
|
359
|
+
*/
|
|
360
|
+
defineWithMethodCaller(is?: string): BehaviorBuilder<
|
|
361
|
+
Empty,
|
|
362
|
+
Empty,
|
|
363
|
+
Empty,
|
|
364
|
+
Empty,
|
|
365
|
+
never,
|
|
366
|
+
never
|
|
367
|
+
> {
|
|
368
|
+
return new BehaviorBuilder(is, this)
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/** @internal */
|
|
372
|
+
_$registerComponent(is: string, comp: GeneralComponentDefinition) {
|
|
373
|
+
this._$list[is] = comp
|
|
374
|
+
this._$behaviorList[is] = comp.behavior as unknown as GeneralBehavior
|
|
375
|
+
const arr = this._$listWaiting[is]
|
|
376
|
+
if (arr) {
|
|
377
|
+
delete this._$listWaiting[is]
|
|
378
|
+
arr.call(comp)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** @internal */
|
|
383
|
+
_$registerBehavior(is: string, beh: GeneralBehavior) {
|
|
384
|
+
this._$behaviorList[is] = beh
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Assign a public alias to a component
|
|
389
|
+
*
|
|
390
|
+
* The alias can be used in other component spaces which imported this component space.
|
|
391
|
+
* One component may have multiple aliases.
|
|
392
|
+
*/
|
|
393
|
+
exportComponent(alias: string, is: string) {
|
|
394
|
+
const comp = this._$list[is]
|
|
395
|
+
if (!comp) {
|
|
396
|
+
throw new Error(`There is no component "${is}" for aliasing`)
|
|
397
|
+
}
|
|
398
|
+
this._$pubList[alias] = comp
|
|
399
|
+
const arr = this._$pubListWaiting[is]
|
|
400
|
+
if (arr) {
|
|
401
|
+
delete this._$pubListWaiting[is]
|
|
402
|
+
arr.call(comp)
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Assign a public alias to a behavior
|
|
408
|
+
*
|
|
409
|
+
* The alias can be used in other component spaces which imported this component space.
|
|
410
|
+
* One behavior may have multiple aliases.
|
|
411
|
+
*/
|
|
412
|
+
exportBehavior(alias: string, is: string) {
|
|
413
|
+
const beh = this._$behaviorList[is]
|
|
414
|
+
if (!beh) {
|
|
415
|
+
throw new Error(`There is no behavior "${is}" for aliasing`)
|
|
416
|
+
}
|
|
417
|
+
this._$pubBehaviorList[alias] = beh
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/** @internal */
|
|
421
|
+
_$componentWaitingList(
|
|
422
|
+
path: string,
|
|
423
|
+
relPath: string,
|
|
424
|
+
): ComponentWaitingList | null {
|
|
425
|
+
const { domain, absPath } = normalizeUrl(path, relPath)
|
|
426
|
+
let waiting: {
|
|
427
|
+
[path: string]: ComponentWaitingList
|
|
428
|
+
} | null
|
|
429
|
+
if (domain) {
|
|
430
|
+
const target = this._$importedSpaces[domain]
|
|
431
|
+
if (target) {
|
|
432
|
+
const { space, privateUse } = target
|
|
433
|
+
if (privateUse) {
|
|
434
|
+
if (space._$list[absPath]) {
|
|
435
|
+
return null
|
|
436
|
+
}
|
|
437
|
+
waiting = space._$listWaiting
|
|
438
|
+
} else {
|
|
439
|
+
if (space._$pubList[absPath]) {
|
|
440
|
+
return null
|
|
441
|
+
}
|
|
442
|
+
waiting = space._$pubListWaiting
|
|
443
|
+
}
|
|
444
|
+
} else {
|
|
445
|
+
return null
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
if (this._$list[absPath]) {
|
|
449
|
+
return null
|
|
450
|
+
}
|
|
451
|
+
waiting = this._$listWaiting
|
|
452
|
+
}
|
|
453
|
+
let wl = waiting[absPath]
|
|
454
|
+
if (wl) return wl
|
|
455
|
+
wl = waiting[absPath] = new ComponentWaitingList()
|
|
456
|
+
return wl
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
getWaitingComponents() {
|
|
460
|
+
return Object.keys(this._$listWaiting)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Create a component by URL
|
|
465
|
+
*
|
|
466
|
+
* This `url` can contain params (started with "?" character).
|
|
467
|
+
* The params will try to be set to component properties (if matches the property name).
|
|
468
|
+
*/
|
|
469
|
+
createComponentByUrl(
|
|
470
|
+
tagName: string,
|
|
471
|
+
url: string,
|
|
472
|
+
genericTargets: { [name: string]: string } | null,
|
|
473
|
+
backendContext: GeneralBackendContext | null,
|
|
474
|
+
): GeneralComponent {
|
|
475
|
+
let domainPath = url
|
|
476
|
+
let paramStr: string | null = null
|
|
477
|
+
|
|
478
|
+
// parse URL
|
|
479
|
+
const hashSepIndex = domainPath.indexOf('#')
|
|
480
|
+
if (hashSepIndex >= 0) {
|
|
481
|
+
domainPath = domainPath.slice(0, hashSepIndex)
|
|
482
|
+
}
|
|
483
|
+
const paramSepIndex = domainPath.indexOf('?')
|
|
484
|
+
if (paramSepIndex >= 0) {
|
|
485
|
+
paramStr = domainPath.slice(paramSepIndex + 1)
|
|
486
|
+
domainPath = domainPath.slice(0, paramSepIndex)
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// find target components
|
|
490
|
+
const compDef = this.getComponentByUrl(domainPath, '')
|
|
491
|
+
let genericImpls: { [key: string]: GeneralComponentDefinition } | null = null
|
|
492
|
+
if (genericTargets) {
|
|
493
|
+
genericImpls = Object.create(null) as { [key: string]: GeneralComponentDefinition }
|
|
494
|
+
Object.keys(genericTargets).forEach((key) => {
|
|
495
|
+
const url = genericTargets[key]!
|
|
496
|
+
const compDef = this.getComponentByUrl(url, '')
|
|
497
|
+
genericImpls![key] = compDef
|
|
498
|
+
})
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// create the component
|
|
502
|
+
const comp = Component.createWithGenericsAndContext(
|
|
503
|
+
tagName,
|
|
504
|
+
compDef,
|
|
505
|
+
genericImpls,
|
|
506
|
+
backendContext,
|
|
507
|
+
(comp) => {
|
|
508
|
+
// set params if provided
|
|
509
|
+
if (paramStr) {
|
|
510
|
+
let needApplyUpdates = false
|
|
511
|
+
paramStr.split('&').forEach((kv) => {
|
|
512
|
+
const kvSepIndex = kv.indexOf('=')
|
|
513
|
+
if (kvSepIndex >= 0) {
|
|
514
|
+
const key = decodeURIComponent(kv.slice(0, kvSepIndex))
|
|
515
|
+
const value = decodeURIComponent(kv.slice(kvSepIndex + 1))
|
|
516
|
+
if (comp._$dataGroup.replaceProperty(key, value)) {
|
|
517
|
+
needApplyUpdates = true
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
})
|
|
521
|
+
if (needApplyUpdates) comp.applyDataUpdates()
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
) as GeneralComponent
|
|
525
|
+
|
|
526
|
+
return comp
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Define a trait behavior
|
|
531
|
+
*
|
|
532
|
+
* A trait behavior
|
|
533
|
+
* Optionally, the trait behavior can add a conversion function.
|
|
534
|
+
* This function can convert the implementation to another interface.
|
|
535
|
+
*/
|
|
536
|
+
defineTraitBehavior<TIn extends { [key: string]: any }>(): TraitBehavior<TIn, TIn>;
|
|
537
|
+
defineTraitBehavior<
|
|
538
|
+
TIn extends { [key: string]: any },
|
|
539
|
+
TOut extends { [key: string]: any },
|
|
540
|
+
>(trans: (impl: TIn) => TOut): TraitBehavior<TIn, TOut>;
|
|
541
|
+
defineTraitBehavior<
|
|
542
|
+
TIn extends { [key: string]: any },
|
|
543
|
+
TOut extends { [key: string]: any },
|
|
544
|
+
>(trans?: (impl: TIn) => TOut): TraitBehavior<TIn, TOut> {
|
|
545
|
+
return new TraitBehavior<TIn, TOut>(this, trans)
|
|
546
|
+
}
|
|
547
|
+
}
|