The main purpose of the schema manager is to provide a simple and uniform api to interact with.
The process involves two distinct stages:
- Initialization: This is a one-time occurrence where all necessary resources are loaded and set up properly to enable the system to function.
- Generation: This stage can be repeated multiple times. It involves the actual operation or production process of the system once initialization is complete.
Initialization
- Create the parser
- Create the schema manager and pass it the parser
- Load the providers that will process the schema
Example
const parser = new HTMLParser();
const manager = new Schema(parser);
await parser.initialize();
await manager.register(crs.material.HeaderProvider);
await manager.register(crs.material.ButtonProvider);
You can see above that we refer to two providers here.
- HeaderProvider – parses and generates header UI
- ButtonProvider – parses and generates button UI
The classes in question are registered on a global object named ‘crs.materials’. When they are registered, new instances of these classes are created to carry out their designated tasks. These instances are dynamic, not static, as they may need to maintain an internal state while parsing. After the parsing is complete, this internal state is reset.
It’s important to note that this method is designed to parse only one schema at a time. To process multiple schemas simultaneously, you would need to duplicate the aforementioned setup and run it on a separate thread.
However, considering the potential strain on memory resources, and given that parsing is typically a quick operation, running multiple threads might not be necessary.
Loading multiple providers
In the provided example of initialization, we utilize the “register” method to load providers. Additionally, there’s a “load” method, which differs as it processes and registers a collection of items.
Most of the workload falls on the parser. Therefore, you can implement a custom load method in the parser. This method would load providers from a file and, for each provider, employ the register method to add it to the provider system.
await manager.load([...]);
Custom loading of providers
While this example demonstrates how to register additional providers, it’s crucial to understand that providers themselves also register the necessary providers during their initialization. The key concept here is that a provider should autonomously load the providers it requires, while also being extendable externally, which is facilitated through the ‘register’ and ‘load’ methods.
If you’re not enhancing the parser’s capabilities, you might opt to bypass the provider registration in the schema manager. However, if you wish to prevent the parser from loading its default providers, you can omit the parser.initialize
method and selectively load only the providers you require.
Generation
- Load the schema to process
- Call the parse method on the schema manager
- Interpret the created user interface (using parse method) and direct it to the system component responsible for further processing.
Example
const html = await manager.parse(schema);
document.body.innerHTML = html;
Parsing context
You have the option to pass a context object as a parameter to the parse method of the schema manager. This is particularly useful when a provider needs to reference specific context data. For instance, in scenarios where you aim to generate static content during UI generation, this context can be provided to the providers. A common use case is passing translation information, allowing labels to be created with the correct translation as part of the UI generation process.
const html = await manager.parse(schema, context);
document.body.innerHTML = html;
Each provider has a “process” method that is used to generate the UI for the current schema item and context.
export default class MyProvider extends BaseProvider
// ... other provider parts
async process(item, ctx) {
return `<h2>${ctx.translations.heading}</h2>`
}
}
The system makes no presumptions about the nature of the context (ctx) object. You should pass whatever is necessary for your providers, if they require any specific information.