Luban H5 Work/Pages/Elements JSON Schema: Structure, Fields, and Implementation
The Luban H5 JSON schema organizes H5 projects into a three-tier hierarchy where the root pages object maps page IDs to page configurations, each containing a components object that defines individual elements with properties like type, props, style, animation, and events.
The ly525/luban-h5 repository stores interactive H5 page configurations in a strict JSON format that powers its open-source visual page builder. Understanding the work/pages/elements JSON schema is essential for developers customizing project exports, extending the component library, or integrating the renderer into custom pipelines.
Overview of the Hierarchical Schema
The schema follows a tree structure with three primary levels. At the top, the work object contains a pages map. Each page entry holds metadata and a components collection (synonymous with elements). Every component represents a visual element with configurable properties.
The Root pages Object
The root of the work JSON contains a pages field, which is an object (dictionary) rather than an array. Keys are unique page identifiers (e.g., page_1, page_2), and values are page configuration objects containing name, background, width, height, and the components map. This structure allows O(1) page lookup and is defined in back-end/h5-api/api/work/documentation/1.0.0/work.json.
Page Configuration and the components Map
Within each page, the components property stores all visual elements for that canvas. Keys are element IDs (e.g., elem_123), and values are element definition objects. This map enables direct element access for updates, as seen in front-end/h5/src/store/modules/work.js where mutations modify specific components entries by ID.
Element Object Structure
An element object defines a single UI component through seven primary fields: type, component, props, style, animation, events, dataSource, and children. All fields are optional except type and component, which are required for the renderer to instantiate the correct Vue component. The schema is flexible, allowing elements to omit unused sections such as animation or dataSource.
Detailed Element Property Reference
Each property in an element object controls a specific aspect of rendering, styling, or behavior.
Component Identification (type and component)
The type field specifies the UI category (e.g., image, text, button, shape, group), determining which icon and default settings appear in the editor. The component field provides the internal renderer name (e.g., Image, TextBlock) used by front-end/h5/src/components/Renderer.vue to map JSON definitions to Vue component registrations.
Styling and Positioning (style object)
The style object contains CSS-like properties defining layout and appearance: width, height, top, left, rotate (rotation in degrees), opacity (0-1), border, and boxShadow. All measurements are stored as numbers representing pixels or as hex color strings, enabling the renderer to apply inline styles directly.
Animation Configuration (animation)
The optional animation object controls entrance or emphasis effects with properties: type (animation name like fadeIn or slideUp), duration (milliseconds), delay (milliseconds), and easing (timing function such as easeOutQuad). If omitted, the element renders statically without motion, as handled by the animation runtime in the front-end engine.
Event Handling (events)
The events object maps DOM event names to handler definitions. Values are stringified JavaScript functions or global function references (e.g., "click": "function() { alert('clicked'); }"). The renderer attaches these listeners during component mount, parsing the strings via new Function() or mapping to predefined actions.
Data Binding and Nesting (dataSource and children)
The dataSource field configures dynamic data fetching, containing type (api or mock), url, method, and params, allowing elements to render live content. The children field is an array of element ID strings used exclusively by container-type components (e.g., group), establishing a parent-child hierarchy that the renderer resolves into nested Vue components.
Working with the Schema in Code
Developers interact with the schema by reading the work JSON, mutating the components map, and triggering re-renders.
Rendering a Page from JSON
To render a page, iterate over the components map and instantiate the corresponding Vue component for each entry.
import { renderComponent } from '@/utils/renderer';
function renderPage(pageData) {
Object.entries(pageData.components).forEach(([elemId, element]) => {
renderComponent(element, elemId); // Maps type to Vue component
});
}
Programmatically Adding Elements
You can mutate the work object directly to inject new elements at runtime.
function addTextElement(work, pageId, textContent) {
const page = work.pages[pageId];
const newId = `elem_${Date.now()}`;
page.components[newId] = {
type: 'text',
component: 'TextBlock',
props: { text: textContent },
style: { top: 100, left: 50, fontSize: 24, color: '#333' },
animation: { type: 'fadeIn', duration: 300 }
};
return newId;
}
Exporting the Work Configuration
Serialize the entire work object to JSON for persistence or server-side storage.
import fs from 'fs';
const workJson = JSON.stringify(work, null, 2);
fs.writeFileSync('work-config.json', workJson);
Key Implementation Files
The following source files define and consume the schema:
- [
back-end/h5-api/api/work/models/Work.settings.json](https://github.com/ly525/luban-h5/blob/master/back-end/h5-api/api/work/models/Work.settings.json) – Defines default work structure and validation rules. - [
back-end/h5-api/api/work/documentation/1.0.0/work.json](https://github.com/ly525/luban-h5/blob/master/back-end/h5-api/api/work/documentation/1.0.0/work.json) – Provides a complete example of the JSON schema including pages and components. - [
back-end/h5-api/extensions/documentation/documentation/1.0.0/full_documentation.json](https://github.com/ly525/luban-h5/blob/master/back-end/h5-api/extensions/documentation/documentation/1.0.0/full_documentation.json) – Aggregated API documentation referencing the work entity schema. - [
front-end/h5/src/store/modules/work.js](https://github.com/ly525/luban-h5/blob/master/front-end/h5/src/store/modules/work.js) – Vuex store managing work state and mutations on thepagesandcomponentsobjects. - [
front-end/h5/src/components/Renderer.vue](https://github.com/ly525/luban-h5/blob/master/front-end/h5/src/components/Renderer.vue) – Core component that traverses the schema to render the visual tree and resolve nested children.
Summary
- The work object contains a pages map where keys are page IDs and values hold page metadata plus a components object.
- Each element in
componentsrequirestypeandcomponentfields, with optionalprops,style,animation,events,dataSource, andchildren. - The style object uses pixel-based numeric values for positioning and sizing.
- Animation and events are optional objects controlling motion and interactivity.
- DataSource enables API bindings, while children supports nested group structures.
- Source code in
back-end/h5-api/api/work/documentation/1.0.0/work.jsonandfront-end/h5/src/components/Renderer.vuedemonstrates the schema implementation.
Frequently Asked Questions
What is the root structure of a Luban H5 work JSON?
The root is an object containing a pages field, which is a dictionary mapping page IDs (like page_1) to page objects. Each page object includes layout metadata (width, height, background) and a components object that holds all elements for that page, as defined in back-end/h5-api/api/work/documentation/1.0.0/work.json.
How are elements organized within a page?
Elements are stored in the components object (also referred to as the elements map) inside each page definition. The keys are unique element IDs (e.g., elem_123), and the values are element configuration objects containing type, props, style, and other properties, enabling direct key-based access for rapid updates.
What properties define an element's appearance and behavior?
An element's appearance is controlled by the style object (position, size, rotation, opacity) and props (content-specific attributes like text or image src). Behavior is governed by events (click handlers) and animation (entrance effects), while dataSource configures dynamic content fetching from external APIs.
How does the renderer handle nested element groups?
When an element has a children array (used by group-type components), the renderer recursively processes each child ID listed in the array, looking up the corresponding element definition in the page's components map. This creates a nested DOM tree within the parent container, as implemented in front-end/h5/src/components/Renderer.vue.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →