Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F7511317
nested-component.ts
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
nested-component.ts
View Options
import
{
is
,
predicates
}
from
"@sealcode/ts-predicates"
;
import
{
ComponentArgument
}
from
"./component-argument.js"
;
import
{
ContainerArgument
}
from
"./container-argument.js"
;
import
{
Registry
}
from
"../registry.js"
;
import
{
Enum
}
from
"./enum.js"
;
import
{
JDDContext
}
from
"../jdd-context.js"
;
import
{
Structured
}
from
"./structured.js"
;
import
{
componentNameToCSSClump
}
from
"../clumps.js"
;
export
class
NestedComponent
extends
ContainerArgument
<
Record
<
string
,
unknown
>
,
Record
<
string
,
unknown
>
>
{
getTypeName
()
{
return
"nested-component"
;
}
getComponentArgument
(
registry
:
Registry
)
{
const
dropdown
=
new
Enum
(
Object
.
keys
(
registry
.
getAll
()));
dropdown
.
parent_argument
=
this
;
return
dropdown
;
}
getInnerStructure
(
registry
:
Registry
,
component_name
:
string
)
:
Record
<
string
,
ComponentArgument
<
unknown
>>
{
return
registry
.
get
(
component_name
)
?
.
getArguments
()
||
{};
}
getStructure
(
registry
:
Registry
,
component_name
:
string
)
{
return
{
component_name
:
this
.
getComponentArgument
(
registry
),
[
`
${
component_name
}
:values`
]
:
new
Structured
(
this
.
getInnerStructure
(
registry
,
component_name
)
),
};
}
getSubArgument
(
ctx
:
JDDContext
,
[
key
,
...
rest
]
:
string
[],
value
:
Record
<
string
,
unknown
>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
)
:
readonly
[
ComponentArgument
<
any
>
|
null
,
string
[],
unknown
]
{
if
(
key
==
"component_name"
)
{
const
dropdown
=
this
.
getComponentArgument
(
ctx
.
registry
);
return
[
dropdown
,
rest
,
{}];
}
// the other key in the path can only be the component name + a colon:
if
(
key
.
endsWith
(
":values"
))
{
const
component_name
=
key
.
replace
(
":values"
,
""
);
const
structured
=
new
Structured
(
this
.
getInnerStructure
(
ctx
.
registry
,
component_name
)
);
return
<
const
>
[
structured
||
null
,
rest
,
structured
?
value
[
key
]
?
structured
.
receivedToParsed
(
ctx
,
value
[
key
]
as
Record
<
string
,
unknown
>
)
:
structured
.
getExampleValue
(
ctx
)
:
{},
];
}
// invalid argument
console
.
error
(
"Invalid argument for component jdd arg:"
,
key
,
rest
,
value
);
return
[
null
,
[],
{}];
}
countWords
(
ctx
:
JDDContext
,
value
:
Record
<
string
,
unknown
>
)
:
number
{
const
component_name
=
value
.
component_name
as
string
;
const
component_values
=
value
[
`
${
component_name
}
:values`
]
as
Record
<
string
,
unknown
>
;
return
Object
.
entries
(
component_values
).
reduce
((
acc
,
[
key
,
val
])
=>
{
if
(
!
this
.
getInnerStructure
(
ctx
.
registry
,
component_name
)[
key
])
{
console
.
warn
(
`Key
${
key
}
doesn't exist in structured argument`
);
return
acc
+
0
;
}
return
(
acc
+
this
.
getInnerStructure
(
ctx
.
registry
,
component_name
)[
key
].
countWords
(
ctx
,
val
)
);
},
0
);
}
async
getEmptyValue
(
ctx
:
JDDContext
)
:
Promise
<
Record
<
string
,
unknown
>>
{
const
component_name
=
Object
.
keys
(
ctx
.
registry
.
getAll
())[
0
];
return
{
component_name
,
[
`
${
component_name
}
:values`
]
:
Object
.
fromEntries
(
await
Promise
.
all
(
Object
.
entries
(
this
.
getInnerStructure
(
ctx
.
registry
,
component_name
)
).
map
(
async
([
name
,
arg
])
=>
[
name
,
await
arg
.
getEmptyValue
(
ctx
),
])
)
)
as
Record
<
string
,
unknown
>
,
};
}
async
getExampleValue
(
context
:
JDDContext
)
{
const
component_name
=
Object
.
keys
(
context
.
registry
.
getAll
())[
0
];
if
(
this
.
example_values
.
length
)
{
return
super
.
getExampleValue
(
context
);
}
const
result
=
{
component_name
,
[
`
${
component_name
}
:values`
]
:
Object
.
fromEntries
(
await
Promise
.
all
(
Object
.
entries
(
this
.
getInnerStructure
(
context
.
registry
,
component_name
)
).
map
(
async
([
name
,
arg
])
=>
[
name
,
await
arg
.
getExampleValue
(
context
),
])
)
)
as
Record
<
string
,
unknown
>
,
};
return
result
;
}
async
processAllSubarguments
(
context
:
JDDContext
,
input
:
unknown
,
processing_function
:
(
argument
:
ComponentArgument
<
unknown
>
,
value
:
unknown
)
=>
Promise
<
unknown
>
)
:
Promise
<
Record
<
string
,
unknown
>
|
Record
<
string
,
unknown
>
[]
>
{
if
(
!
is
(
input
,
predicates
.
object
))
{
throw
new
Error
(
`Not an object:
${
input
as
string
}
`
);
}
const
component_name
=
input
.
component_name
as
string
;
const
result
:
Record
<
string
,
unknown
>
=
{};
const
subinput
=
input
[
`
${
component_name
}
:values`
]
||
{};
if
(
!
is
(
subinput
,
predicates
.
object
))
{
throw
new
Error
(
`Not an object:
${
subinput
as
string
}
`
);
}
await
Promise
.
all
(
Object
.
entries
(
subinput
).
map
(
async
([
obj_key
,
obj_value
])
=>
{
const
nested_arg_type
:
ComponentArgument
<
unknown
>
=
this
.
getInnerStructure
(
context
.
registry
,
component_name
)[
obj_key
];
if
(
!
nested_arg_type
)
{
return
[
obj_key
,
null
];
}
const
new_value
=
await
processing_function
(
nested_arg_type
,
obj_value
);
result
[
obj_key
]
=
new_value
;
})
);
// if we're in a list and any of the values return an array, we will multiply the object
if
(
this
.
hasParent
(
"list"
))
{
const
keys_with_unexpected_arrays
=
Object
.
entries
(
result
)
.
filter
(([
key
,
value
])
=>
{
const
nested_arg_type
:
ComponentArgument
<
unknown
>
=
this
.
getInnerStructure
(
context
.
registry
,
component_name
)[
key
];
return
(
nested_arg_type
.
getTypeName
()
!==
"list"
&&
Array
.
isArray
(
value
)
);
})
.
map
(([
key
])
=>
key
);
if
(
keys_with_unexpected_arrays
.
length
>
1
)
{
throw
new
Error
(
"Multiplying on more than one field at the same time is not implemented yet"
);
}
if
(
keys_with_unexpected_arrays
.
length
==
1
)
{
const
key
=
keys_with_unexpected_arrays
[
0
];
const
old_result
=
result
;
const
array
=
old_result
[
key
];
if
(
!
Array
.
isArray
(
array
))
{
throw
new
Error
(
"expected an array"
);
}
return
array
.
map
((
value
:
unknown
)
=>
({
...
old_result
,
[
key
]
:
value
,
}));
}
else
{
return
{
component_name
,
[
`
${
component_name
}
:values`
]
:
result
,
};
}
}
else
{
return
{
component_name
,
[
`
${
component_name
}
:values`
]
:
result
};
}
}
static
render
({
jdd_context
,
data
,
classes
=
[],
index
=
-
1
,
}
:
{
jdd_context
:
JDDContext
;
data
:
Record
<
string
,
unknown
>
;
classes
?:
string
[];
index
?:
number
;
})
{
const
component_name
=
data
.
component_name
as
string
;
const
component
=
jdd_context
.
registry
.
get
(
component_name
);
if
(
!
component
)
{
return
"Unknown component: ${component_name}"
;
}
const
args
=
data
[
`
${
component_name
}
:values`
]
as
Record
<
string
,
unknown
>
;
return
component
.
toHTML
({
args
,
classes
,
jdd_context
,
index
});
}
static
getCSSClumpsForNested
(
jdd_context
:
JDDContext
,
data
:
Record
<
string
,
unknown
>
)
:
string
[]
{
const
component_name
=
data
.
component_name
as
string
;
const
component
=
jdd_context
.
registry
.
get
(
component_name
);
if
(
!
component
)
{
console
.
error
(
"Unknown component: ${component_name}"
);
return
[];
}
const
args
=
data
[
`
${
component_name
}
:values`
]
as
Record
<
string
,
unknown
>
;
return
[
componentNameToCSSClump
(
component_name
),
...
component
.
getCSSClumps
(
jdd_context
,
args
),
];
}
async
receivedToParsed
(
context
:
JDDContext
,
value
:
Record
<
string
,
unknown
>
)
:
Promise
<
Record
<
string
,
unknown
>>
{
const
result
=
await
super
.
receivedToParsed
(
context
,
value
);
const
component_name
=
result
.
component_name
;
if
(
!
is
(
component_name
,
predicates
.
string
))
{
throw
new
Error
(
`Not an object:
${
component_name
as
string
}
`
);
}
if
(
component_name
)
{
// delete previous values after changing the component
for
(
const
invalid_key
of
Object
.
keys
(
result
).
filter
(
(
e
)
=>
e
.
endsWith
(
":values"
)
&&
e
!==
`
${
component_name
}
:values`
))
{
delete
result
[
invalid_key
];
}
// generate new example values for the new component
if
(
Object
.
keys
(
result
[
`
${
component_name
}
:values`
]
as
Record
<
string
,
unknown
>
).
length
==
0
)
{
result
[
`
${
component_name
}
:values`
]
=
await
context
.
registry
.
get
(
component_name
)
?
.
getExampleValues
(
context
);
}
}
return
result
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-Algol68
Expires
Mon, Jul 21, 00:20 (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
837930
Default Alt Text
nested-component.ts (7 KB)
Attached To
Mode
rJDD jdd
Attached
Detach File
Event Timeline
Log In to Comment