vite-plugin-json-partial-merge
v0.4.0
Published
Vite plugin for JSON partial/merge system - ideal for Shopify theme development
Maintainers
Readme
vite-plugin-json-partial-merge
A Vite plugin for JSON partial/merge system - ideal for Shopify theme development. This plugin allows you to create reusable JSON configuration blocks and merge multiple JSON files during the build process.
Features
- Partial Imports: Import reusable JSON configuration blocks
- ID Transformations: Prepend prefixes or replace IDs to avoid conflicts
- Selective Inclusion: Exclude specific settings using the
exceptoption (filters by bothidandtypefields) - Add Settings: Append settings to Shopify blocks with support for nested partials
- Directory Merging: Combine multiple JSON files into a single array
- Nested Partials: Partials can reference other partials (up to 5 levels deep)
- Type-Safe: Full TypeScript support with strict type checking
- Well-Tested: 92.79% code coverage with comprehensive test suite
Installation
npm install -D vite-plugin-json-partial-mergepnpm add -D vite-plugin-json-partial-mergeyarn add -D vite-plugin-json-partial-mergeQuick Start
1. Configure Vite
// vite.config.ts
import { defineConfig } from 'vite';
import jsonPartialMerge from 'vite-plugin-json-partial-merge';
export default defineConfig({
plugins: [
jsonPartialMerge({
partialsDir: 'src/partials', // Default: 'src/partials'
}),
],
});2. Create a Partial
Create a reusable JSON partial in src/partials/buttonSettings.json:
[
{
"type": "text",
"id": "button_text",
"label": "Button Text",
"default": "Click me"
},
{
"type": "url",
"id": "button_url",
"label": "Button URL",
"default": "#"
}
]3. Use the Partial
Reference the partial in your JSON file:
{
"name": "Hero Section",
"settings": [
{
"type": "text",
"id": "title",
"label": "Title"
},
{
"type": "partial",
"with": "buttonSettings"
}
]
}4. Build
During the Vite build, the partial will be expanded inline:
{
"name": "Hero Section",
"settings": [
{
"type": "text",
"id": "title",
"label": "Title"
},
{
"type": "text",
"id": "button_text",
"label": "Button Text",
"default": "Click me"
},
{
"type": "url",
"id": "button_url",
"label": "Button URL",
"default": "#"
}
]
}Plugin Options
partialsDir
Directory containing partial JSON files.
- Type:
string - Default:
'src/partials'
jsonPartialMerge({
partialsDir: 'config/partials',
});include
File patterns to include for processing.
- Type:
string | string[] - Default:
'**/*.json'(all JSON files)
jsonPartialMerge({
include: ['src/**/*.json', 'config/**/*.json'],
});exclude
File patterns to exclude from processing.
- Type:
string | string[] - Default:
undefined
jsonPartialMerge({
exclude: ['node_modules/**', 'dist/**'],
});Directive Syntax
Partial Import
Import a reusable partial:
{
"type": "partial",
"with": "partialName"
}Partial with ID Prefix
Add a prefix to all IDs to avoid conflicts:
{
"type": "partial",
"with": "buttonSettings",
"prepend": "hero"
}Result: button_text → hero_button_text
Partial with ID Replacement
Map specific IDs to new values:
{
"type": "partial",
"with": "buttonSettings",
"replace": {
"button_text": "cta_text",
"button_url": "cta_url"
}
}Result: button_text → cta_text, button_url → cta_url
Partial with Exclusions
Omit specific settings from the partial by ID or type:
{
"type": "partial",
"with": "sectionSettings",
"except": ["background_image", "anchor_id", "header", "paragraph"]
}Note: The except array can filter objects by either their id field or type field.
Add Settings to Blocks
Append settings to each block's settings array (for Shopify blocks):
{
"type": "partial",
"with": "shopifyBlocks",
"addSettings": [
{ "type": "checkbox", "id": "visible", "label": "Visible", "default": true },
{ "type": "text", "id": "custom_class", "label": "Custom CSS Class" }
]
}How it works: If the loaded partial is an array of objects with a settings property, the addSettings array will be appended to each object's settings.
Use case: Add common settings (like visibility toggles or CSS classes) to multiple block types at once.
Nested partials: You can use partials inside addSettings:
{
"type": "partial",
"with": "shopifyBlocks",
"addSettings": [
{ "type": "partial", "with": "commonBlockSettings" }
]
}Note: The addSettings feature works with both partial and merge directives.
Combining Options
You can use multiple options together:
{
"type": "partial",
"with": "sectionSettings",
"prepend": "hero",
"except": ["hero_background_image"],
"replace": {
"padding_top": "custom_padding_top"
}
}Processing order: replace → prepend → filter → addSettings
Directory Merge
Merge multiple JSON files from a directory:
{
"type": "merge",
"directory": ".",
"except": ["settings_data.json", "settings_schema.json"]
}Use case: Consolidate modular configuration files into a single array (e.g., Shopify theme settings).
Use Cases
Shopify Theme Development
This plugin was designed for Shopify theme development, where you often need to:
- Share common settings across multiple sections
- Build a consolidated
settings_schema.jsonfrom modular config files - Avoid ID conflicts when reusing settings
Example: Building Theme Settings
Directory structure:
src/config/
settings_schema.json → {"type": "merge", "directory": ".", "except": [...]}
0_theme_info.json → {"name": "theme_info", ...}
1_colors.json → {"name": "Colors", "settings": [...]}
2_buttons.json → {"name": "Buttons", "settings": [...]}
settings_data.json → (excluded from merge)Build output (dist/config/settings_schema.json):
[
{"name": "theme_info", ...},
{"name": "Colors", "settings": [...]},
{"name": "Buttons", "settings": [...]}
]Best Practices
- Keep partials focused: One concern per partial (e.g., visibility, buttons, colors)
- Use descriptive names:
buttonSettingsinstead ofbuttons - Avoid deep nesting: Max 2-3 levels of partial-in-partial
- Minimize
replace: Preferprependor inline settings for clarity - Test builds: Ensure partials expand correctly with
npm run build - Alphabetical ordering: Name config files with numeric prefixes (
0_,1_,2_) to control merge order
Error Handling
Partial must have "with"
Error: Partials must have a "with" property
Fix: Ensure the "with" property is present and points to a valid partial name.
{
"type": "partial",
"with": "partialName" // ← Required
}Partial must be array
Error: All partials must be arrays!
Fix: Ensure partial files export an array [...], not an object {...}.
// ✓ Correct
[
{"type": "text", "id": "heading"}
]
// ✗ Incorrect
{
"setting": {"type": "text", "id": "heading"}
}Could not load partial
Error: Could not load partial: partialName.json not found
Fix: Check that src/partials/partialName.json exists and has valid JSON syntax.
Circular reference
Error: Circular partial reference detected: partialName
Fix: Check for circular partial references (A includes B, B includes A).
Could not read directory
Error: Could not read directory: directoryPath
Fix: Ensure the directory path in merge directive is correct and accessible.
TypeScript
The plugin is written in TypeScript and provides full type definitions out of the box.
import jsonPartialMerge, {
type PluginOptions,
type PartialOptions,
type MergeOptions,
} from 'vite-plugin-json-partial-merge';
const options: PluginOptions = {
partialsDir: 'src/partials',
include: '**/*.json',
};API Reference
jsonPartialMerge(options?: PluginOptions): Plugin
Creates a Vite plugin instance.
Parameters:
options(optional): Plugin configuration
Returns: Vite plugin object
Types
PluginOptions
interface PluginOptions {
partialsDir?: string; // Default: 'src/partials'
include?: string | string[]; // Default: '**/*.json'
exclude?: string | string[]; // Default: undefined
}PartialOptions
interface PartialOptions {
type: 'partial';
with: string; // Partial file name (without .json)
replace?: Record<string, string>; // ID remapping
prepend?: string; // ID prefix
except?: string[]; // IDs or types to exclude
addSettings?: JsonValue[]; // Settings to add to each block's settings array
}MergeOptions
interface MergeOptions {
type: 'merge';
directory: string; // Relative path to directory
except?: string[]; // Filenames to exclude
addSettings?: JsonValue[]; // Settings to add to each block's settings array
}Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT © Evan Ford
Related
- Vite - Next generation frontend tooling
- Shopify Theme Development
