jacob-8/kitbook

Customizable kitbook navigation tree/menu

kristianmandrup opened this issue · 3 comments

Double-Check

Clear description of the requested feature

It feels a bit inconvenient that the current navigation tree is mapped directly to the underlying folder structure in the file system. Would be great if there was a way to configure a mapping to:

  • select specific components of interest
  • avoid deeply nested menu/tree structure
  • be more compatible with shadcn-ui in particular

For shadcn ui, a button component is by default installed in lib/components/ui/button/button.svelte
Would be very nice if this could be mapped to simply lib/shadcn/button in kitbook

Suggested solution

Setup some pattern matching rules that maps to a different structure, such as:

components/ui/**/*.svelte -> shadcn-ui/{name}

As kitbook traverses components, for each file path it could attempt a pattern match in each of the registered patterns and then apply a renaming rule

Alternative

I guess compositions could also alleviate this? Please advise.

Another approach would be to define a structure and for each define patterns (or functions?) for which components should be placed there. This could also allow sorting or relative re-positioning as desired.

{
  "shadcn-ui": ({components}) => {
     return components.filter(...).sort(...)
  } ,
  // ... more rules 

Additional context

I just discovered that there is a _meta.slot. It was unclear how to set the special slot property for the text of the button. I don't see any _meta reference documentation included?

Having looked a bit into kitbook, I think this could be done with an additional optional transform step and a change to the parse pages modules into pages step.

export function groupColocatedModulesIntoPages(...) {
 // ...
  const modules = { ...markdown, ...components, ...variants, ...compositions } as Modules
  const rawModules = { ...componentsRaw, ...variantsRaw, ...compositionsRaw, ...markdownRaw } as RawModules
  const ungroupedPages = parseModulesIntoUngroupedPages(modules, rawModules)
  // Proposed change 
  const { paths, config } = ungroupedPages 
  const groupedPages = groupColocatedPages(paths)
  return config ? config.transformPages(groupedPages) : groupedPages 
}

Each grouped page has the following properties: { name: page.name, url, path: page.path, extensions: [page.ext] }

In addition, to load and apply a kitbook config, it would have to be made available here, I presume?

export async function parseModulesIntoUngroupedPages(
  modules: Modules,
  rawModules: RawModules
): Promise<UngroupedPage<any>[]> {
  const paths = Object.keys(modules);
  if (!paths.length) return [];

  let config: any;

  const transformedPaths = await Promise.all(
    paths.map(async (path) => {
      const { name, ext } = parsePath(path);
      const url = path.replace('src/', '').replace(`.${ext}`, '');

      if (url === 'kitbook.config') {
        // Dynamically import the configuration file from the project root
        const configModule = await import('../../kitbook.config.ts');
        config = configModule.default;
      }

      return {
        path,
        name: removeInitialDigitAndHyphens(name),
        ext,
        url,
        load: {
          loadModule: modules[path],
          loadRaw: rawModules[path],
        },
      };
    })
  );

  // If needed,  call a function from the config to initialize
  if (config && typeof config.initializeConfig === 'function') {
    config.initializeConfig();
  }

  return {
    config,
    paths: transformedPaths,
  };
}

Note: I just discovered that configuration is briefly covered in the kitbook docs

I think this could be done with an additional optional transform step and a change to the parse pages modules into pages step

Yes, I think this would be pretty easy to accomplish. I can allow an optional transform function to be passed in via the kitbook config, and then I would apply it at the appropriate place. Let me think more and get back to you.

@jacob-8 Thanks for responding :)

I think my above suggestion would work well, at least as a prototype impl., with the addition of a placement property.

      return {
        path,
        placement: path, // default placement same as in source tree
        name: removeInitialDigitAndHyphens(name),
        ext,
        url,
        load: {
          loadModule: modules[path],
          loadRaw: rawModules[path],
        },
      };

Then the transform step can transform the placement (in the Kitbook viewer) to a different location and you would have the mapping, when adding new pages so it can use the original path to save the file etc.