Skip to content

Commit

Permalink
feat: _inlineWrapper.svelte - a non recursive decorator that applies …
Browse files Browse the repository at this point in the history
…only to inlined nodes
  • Loading branch information
jakobrosenberg committed Dec 26, 2023
1 parent dddd76c commit 7f688ed
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 38 deletions.
10 changes: 10 additions & 0 deletions lib/buildtime/plugins/filemapper/lib/utils/filenameToOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,14 @@ export const filenameToOptions = node => {
.forEach(node => {
node.meta.noRoute = true
})
descendants
.filter(node => node.name === '_decorator')
.forEach(node => {
node.meta.isDecorator = true
})
descendants
.filter(node => node.name === '_inlineWrapper')
.forEach(node => {
node.meta.isInlineWrapper = true
})
}
6 changes: 5 additions & 1 deletion lib/runtime/Route/Route.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ export class Route {
this.log.debug('load components', this) // ROUTIFY-DEV-ONLY
const nodes = this.fragments.map(fragment => fragment.node)
const multiNodes = nodes
.map(node => node.children.find(node => node.name === '_decorator'))
.map(node =>
node.children.find(
node => node.meta.isDecorator || node.meta.isInlineWrapper,
),
)
.filter(Boolean)

await Promise.all([...nodes, ...multiNodes].map(node => node.loadModule()))
Expand Down
26 changes: 14 additions & 12 deletions lib/runtime/renderer/ComposeFragments.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
import { get } from 'svelte/store'
import { pushToOrReplace } from '../utils/index.js'
import RenderFragment from './RenderFragment.svelte'
import { normalizeDecorator } from './utils/normalizeDecorator.js'
import { normalizeDecorator, normalizeWrapper } from './utils/normalizeDecorator.js'
import { handleRebuildError } from '../utils/messages.js'
import { addFolderDecorator, findActiveChildContext } from './composeFragments.js'
import {
addFolderDecorator,
addFolderWrapper,
findActiveChildContext,
} from './composeFragments.js'
/** @type {RenderContext|RouterContext}*/
export let context
Expand All @@ -14,16 +18,16 @@
const { childFragments } = context
const { decorator } = options
const inlineWrapper =
options.inline?.['wrapper'] && normalizeWrapper(options.inline['wrapper'])
const recursiveDecorators = context.decorators.filter(deco => deco.recursive)
const newDecorators = pushToOrReplace(recursiveDecorators, decorator)
const newDecorators = pushToOrReplace(recursiveDecorators, [decorator, inlineWrapper])
.filter(Boolean)
.map(normalizeDecorator)
// addFolderDecorator returns void if decorator is sync, otherwise it returns a promise
let decoratorReady = !addFolderDecorator(newDecorators, context)?.['then'](
() => (decoratorReady = true),
)
addFolderDecorator(newDecorators, context)
addFolderWrapper(newDecorators, context)
context.buildChildContexts(options, newDecorators)
Expand Down Expand Up @@ -64,8 +68,6 @@
$: _handleChildren($childFragments)
</script>

{#if decoratorReady}
{#each $childContexts as context (context)}
<RenderFragment {context} />
{/each}
{/if}
{#each $childContexts as context (context)}
<RenderFragment {context} />
{/each}
45 changes: 25 additions & 20 deletions lib/runtime/renderer/composeFragments.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { get } from 'svelte/store'
import { RouteFragment } from '../Route/RouteFragment.js'
import { RenderContext } from './RenderContext.js'
import { normalizeWrapper } from './utils/normalizeDecorator.js'

/**
* check if fragments have the same node and all a params are in b.
Expand All @@ -22,36 +23,40 @@ export const nodeIsIndexed = node =>
export const fetchIndexNode = node =>
node.navigableChildren.find(node => node.meta.isDefault)

/**
* @param {RNodeRuntime} node
*/
const findDecorator = node => node?.children.find(node => node.name === '_decorator')

// TODO addFolderDecorator should always be synchronous
/**
*
* @param {Decorator[]} decorators
* @param {RenderContext} context
* @param {RenderContext | RouterContext} context
* @returns {void | Promise<void>}
*/
export const addFolderDecorator = (decorators, context) => {
const folderDecorator = findDecorator(context.node)

if (!folderDecorator) return
const folderDecorator = context['node']?.children.find(node => node.meta.isDecorator)

if (!folderDecorator.module)
return folderDecorator.loadModule().then(() => {
console.warn(`Dynamic import of "${folderDecorator.id}" may cause issues.`)
addFolderDecorator(decorators, context)
if (folderDecorator) {
const options = folderDecorator.module['decorator'] || {}
decorators.push({
component: folderDecorator.module['default'],
recursive: options.recursive ?? folderDecorator.meta.recursive ?? true,
shouldRender:
options.shouldRender ?? folderDecorator.meta.shouldRender ?? (() => true),
})
}
}
/**
*
* @param {Decorator[]} decorators
* @param {RenderContext | RouterContext} context
* @returns {void | Promise<void>}
*/
export const addFolderWrapper = (decorators, context) => {
const inlineWrapper = context['node']?.children.find(
node => node.meta.isInlineWrapper,
)

const options = folderDecorator.module['decorator'] || {}

decorators.push({
component: folderDecorator.module['default'],
recursive: options.recursive ?? folderDecorator.meta.recursive ?? true,
shouldRender: options.shouldRender ?? (() => true),
})
if (inlineWrapper) {
decorators.push(normalizeWrapper(inlineWrapper.module.default))
}
}

export function findNearestInlineContext(context) {
Expand Down
14 changes: 13 additions & 1 deletion lib/runtime/renderer/utils/normalizeDecorator.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
const decoratorDefaults = { recursive: true, shouldRender: () => true }
const decoratorDefaults = {
recursive: true,
shouldRender: () => true,
}
const wrapperDefaults = {
recursive: false,
shouldRender: ({ context }) => context.isInline,
}

/**
* @param {DecoratorInput} decorator
Expand All @@ -9,4 +16,9 @@ export const normalizeDecorator = decorator => {
else return { ...decoratorDefaults, component: decorator }
}

export const normalizeWrapper = wrapper => {
if ('component' in wrapper) return { ...wrapperDefaults, ...wrapper }
else return { ...wrapperDefaults, component: wrapper }
}

export * from './normalizeInline.js'
3 changes: 2 additions & 1 deletion test/integration/routify/__snapshots__/routify.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ export default {
\\"meta\\": {
\\"dynamic\\": true,
\\"dynamicSpread\\": true,
\\"order\\": false
\\"order\\": false,
\\"inline\\": false
},
\\"name\\": \\"[...404]\\",
\\"file\\": {
Expand Down
1 change: 1 addition & 0 deletions types/typedef.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@
* @prop { 'browser'|'ssr'|'always' } context
* @prop { (elem: HTMLElement, instant: boolean) => void } scrollIntoView
* @prop { Object<string, string[]> } params
* @prop { SvelteComponentDev? } wrapper
*/

/**
Expand Down
1 change: 1 addition & 0 deletions typings/lib/runtime/Global/Global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export class AppInstance {
/** @type {import('../helpers/preload.js').RoutesMap} */
routeMaps: import('../helpers/preload.js').RoutesMap;
browserAdapter: BrowserAdapter;
reset(): void;
/** @param {Router} router */
urlFromBrowser: (router: Router) => string;
register(instance: any): AppInstance;
Expand Down
3 changes: 2 additions & 1 deletion typings/lib/runtime/renderer/composeFragments.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ export function findNearestInlineContext(context: any): any;
export function contextHasMatchingFragmentAndParams(f: RouteFragment): (c: RenderContext) => boolean;
export function nodeIsIndexed(node: RNodeRuntime): boolean;
export function fetchIndexNode(node: RNodeRuntime): import("../Instance/RNodeRuntime.js").RNodeRuntime;
export function addFolderDecorator(decorators: Decorator[], context: RenderContext): void | Promise<void>;
export function addFolderDecorator(decorators: Decorator[], context: RenderContext | RouterContext): void | Promise<void>;
export function addFolderWrapper(decorators: Decorator[], context: RenderContext | RouterContext): void | Promise<void>;
export function defaultscrollBoundary(ownContext: any): any;
export function findActiveChildContext(childContexts: RenderContext[], fragment: RouteFragment): RenderContext;
import { RouteFragment } from "../Route/RouteFragment.js";
Expand Down
1 change: 1 addition & 0 deletions typings/lib/runtime/renderer/utils/normalizeDecorator.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export function normalizeDecorator(decorator: DecoratorInput): Decorator;
export function normalizeWrapper(wrapper: any): any;
export * from "./normalizeInline.js";
4 changes: 2 additions & 2 deletions typings/plugins/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { flexMapsPlugin } from "./flexMap/index.js";
import indexByNamePlugin from "./indexByName.js";
export { flexMapsPlugin, indexByNamePlugin };
import indexByPrefixPlugin from "./indexByPrefix/index.js";
export { flexMapsPlugin, indexByPrefixPlugin };
8 changes: 8 additions & 0 deletions typings/plugins/indexByPrefix/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
declare function _default(options: any): {
name: string;
before: string;
build: ({ instance }: {
instance: any;
}) => void;
};
export default _default;
1 change: 1 addition & 0 deletions typings/types/typedef.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ type Inline = {
params: {
[x: string]: string[];
};
wrapper: SvelteComponentDev | null;
};
type DeferredPromise<T> = Promise<T> & {
resolve: (T: any) => void;
Expand Down

0 comments on commit 7f688ed

Please sign in to comment.