@@ -178,7 +178,7 @@ const computeAllowedCategories = ({
178178
179179const defaultComponentContentModel : ContentModel = {
180180 category : "instance" ,
181- children : [ "rich-text" , "instance" , "transparent" ] ,
181+ children : [ "rich-text" , "instance" ] ,
182182} ;
183183
184184const getComponentContentModel = ( meta : undefined | WsComponentMeta ) =>
@@ -187,45 +187,29 @@ const getComponentContentModel = (meta: undefined | WsComponentMeta) =>
187187const isComponentSatisfyingContentModel = ( {
188188 metas,
189189 component,
190- allowedCategories,
190+ allowedParentCategories,
191+ allowedAncestorCategories,
191192} : {
192193 metas : Metas ;
193194 component : string ;
194- allowedCategories : undefined | string [ ] ;
195+ allowedParentCategories : undefined | string [ ] ;
196+ allowedAncestorCategories : undefined | string [ ] ;
195197} ) => {
196198 const contentModel = getComponentContentModel ( metas . get ( component ) ) ;
197199 return (
198200 // body does not have parent
199- allowedCategories === undefined ||
201+ allowedParentCategories === undefined ||
200202 // parents may restrict specific components with none category
201203 // any instances
202204 // or nothing
203- allowedCategories . includes ( component ) ||
204- allowedCategories . includes ( contentModel . category )
205+ allowedParentCategories . includes ( component ) ||
206+ allowedParentCategories . includes ( contentModel . category ) ||
207+ allowedAncestorCategories ?. includes ( component ) === true ||
208+ allowedAncestorCategories ?. includes ( contentModel . category ) === true
205209 ) ;
206210} ;
207211
208- const getComponentChildrenCategories = ( {
209- metas,
210- component,
211- allowedCategories,
212- } : {
213- metas : Metas ;
214- component : string ;
215- allowedCategories : undefined | string [ ] ;
216- } ) => {
217- const contentModel = getComponentContentModel ( metas . get ( component ) ) ;
218- let childrenCategories = contentModel . children ;
219- // transparent categories makes component inherit constraints from parent
220- if ( childrenCategories . includes ( "transparent" ) && allowedCategories ) {
221- childrenCategories = Array . from (
222- new Set ( [ ...childrenCategories , ...allowedCategories ] )
223- ) ;
224- }
225- return childrenCategories ;
226- } ;
227-
228- const computeAllowedComponentCategories = ( {
212+ const computeAllowedAncestorCategories = ( {
229213 instances,
230214 metas,
231215 instanceSelector,
@@ -234,24 +218,43 @@ const computeAllowedComponentCategories = ({
234218 metas : Metas ;
235219 instanceSelector : InstanceSelector ;
236220} ) => {
237- let instance : undefined | Instance ;
238221 let allowedCategories : undefined | string [ ] ;
239222 // skip selected instance for which these constraints are computed
240223 for ( const instanceId of instanceSelector . slice ( 1 ) . reverse ( ) ) {
241- instance = instances . get ( instanceId ) ;
224+ const instance = instances . get ( instanceId ) ;
242225 // collection item can be undefined
243226 if ( instance === undefined ) {
244227 continue ;
245228 }
246- allowedCategories = getComponentChildrenCategories ( {
247- metas,
248- component : instance . component ,
249- allowedCategories,
250- } ) ;
229+ const contentModel = getComponentContentModel (
230+ metas . get ( instance . component )
231+ ) ;
232+ if ( contentModel . descendants ) {
233+ allowedCategories ??= [ ] ;
234+ allowedCategories = [ ...allowedCategories , ...contentModel . descendants ] ;
235+ }
251236 }
252237 return allowedCategories ;
253238} ;
254239
240+ const getAllowedParentCategories = ( {
241+ instances,
242+ metas,
243+ instanceSelector,
244+ } : {
245+ instances : Instances ;
246+ metas : Metas ;
247+ instanceSelector : InstanceSelector ;
248+ } ) => {
249+ const instanceId = instanceSelector [ 1 ] ;
250+ const instance = instances . get ( instanceId ) ;
251+ if ( instance === undefined ) {
252+ return ;
253+ }
254+ const contentModel = getComponentContentModel ( metas . get ( instance . component ) ) ;
255+ return contentModel . children ;
256+ } ;
257+
255258/**
256259 * Check all tags starting with specified instance select
257260 * for example
@@ -294,15 +297,17 @@ export const isTreeSatisfyingContentModel = ({
294297 instanceSelector,
295298 onError,
296299 _allowedCategories : allowedCategories ,
297- _allowedComponentCategories : allowedComponentCategories ,
300+ _allowedAncestorCategories : allowedAncestorCategories ,
301+ _allowedParentCategories : allowedParentCategories ,
298302} : {
299303 instances : Instances ;
300304 props : Props ;
301305 metas : Metas ;
302306 instanceSelector : InstanceSelector ;
303307 onError ?: ( message : string ) => void ;
304308 _allowedCategories ?: string [ ] ;
305- _allowedComponentCategories ?: string [ ] ;
309+ _allowedAncestorCategories ?: string [ ] ;
310+ _allowedParentCategories ?: string [ ] ;
306311} ) : boolean => {
307312 // compute constraints only when not passed from parent
308313 allowedCategories ??= computeAllowedCategories ( {
@@ -311,7 +316,12 @@ export const isTreeSatisfyingContentModel = ({
311316 props,
312317 metas,
313318 } ) ;
314- allowedComponentCategories ??= computeAllowedComponentCategories ( {
319+ allowedParentCategories ??= getAllowedParentCategories ( {
320+ instanceSelector,
321+ instances,
322+ metas,
323+ } ) ;
324+ allowedAncestorCategories ??= computeAllowedAncestorCategories ( {
315325 instanceSelector,
316326 instances,
317327 metas,
@@ -344,7 +354,8 @@ export const isTreeSatisfyingContentModel = ({
344354 const isComponentSatisfying = isComponentSatisfyingContentModel ( {
345355 metas,
346356 component : instance . component ,
347- allowedCategories : allowedComponentCategories ,
357+ allowedParentCategories,
358+ allowedAncestorCategories,
348359 } ) ;
349360 if ( isComponentSatisfying === false ) {
350361 const [ _namespace , name ] = parseComponentName ( instance . component ) ;
@@ -363,6 +374,16 @@ export const isTreeSatisfyingContentModel = ({
363374 }
364375 }
365376 let isSatisfying = isTagSatisfying && isComponentSatisfying ;
377+ const contentModel = getComponentContentModel ( metas . get ( instance . component ) ) ;
378+ allowedCategories = getTagChildrenCategories ( tag , allowedCategories ) ;
379+ allowedParentCategories = contentModel . children ;
380+ if ( contentModel . descendants ) {
381+ allowedAncestorCategories ??= [ ] ;
382+ allowedAncestorCategories = [
383+ ...allowedAncestorCategories ,
384+ ...contentModel . descendants ,
385+ ] ;
386+ }
366387 for ( const child of instance . children ) {
367388 if ( child . type === "id" ) {
368389 isSatisfying &&= isTreeSatisfyingContentModel ( {
@@ -371,12 +392,9 @@ export const isTreeSatisfyingContentModel = ({
371392 metas,
372393 instanceSelector : [ child . value , ...instanceSelector ] ,
373394 onError,
374- _allowedCategories : getTagChildrenCategories ( tag , allowedCategories ) ,
375- _allowedComponentCategories : getComponentChildrenCategories ( {
376- metas,
377- component : instance . component ,
378- allowedCategories : allowedComponentCategories ,
379- } ) ,
395+ _allowedCategories : allowedCategories ,
396+ _allowedParentCategories : allowedParentCategories ,
397+ _allowedAncestorCategories : allowedAncestorCategories ,
380398 } ) ;
381399 }
382400 }
0 commit comments