mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
update: validator,validate,styles (1 files)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
--- Validate styles.json structure and content
|
||||
--- Supports both V1 (array) and V2 (object) schema formats
|
||||
---@param package_path string The path to the package
|
||||
---@return table result Validation result with success and messages
|
||||
|
||||
@@ -28,7 +29,7 @@ local function validate_styles(package_path)
|
||||
return result
|
||||
end
|
||||
|
||||
-- Try to parse JSON (basic validation)
|
||||
-- Try to parse JSON
|
||||
local success, styles = pcall(function()
|
||||
return require("json").decode(content)
|
||||
end)
|
||||
@@ -39,15 +40,28 @@ local function validate_styles(package_path)
|
||||
return result
|
||||
end
|
||||
|
||||
-- Validate it's an array
|
||||
if type(styles) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "styles.json must be an array of style objects")
|
||||
table.insert(result.messages, "styles.json must be either an array (V1) or object (V2)")
|
||||
return result
|
||||
end
|
||||
|
||||
-- Validate each style entry
|
||||
-- Detect schema version
|
||||
local schema_version = styles.schema_version or "1.0.0"
|
||||
|
||||
-- Check if it's V2 (has schema_version or package field)
|
||||
if styles.schema_version or styles.package then
|
||||
return validate_styles_v2(styles, result)
|
||||
else
|
||||
-- V1: Array of style entries
|
||||
return validate_styles_v1(styles, result)
|
||||
end
|
||||
end
|
||||
|
||||
--- Validate V1 schema (array format)
|
||||
local function validate_styles_v1(styles, result)
|
||||
local seen_ids = {}
|
||||
|
||||
for i, style in ipairs(styles) do
|
||||
local prefix = "Style entry #" .. i
|
||||
|
||||
@@ -56,7 +70,6 @@ local function validate_styles(package_path)
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: id")
|
||||
else
|
||||
-- Check for duplicate IDs
|
||||
if seen_ids[style.id] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has duplicate id: " .. style.id)
|
||||
@@ -68,7 +81,6 @@ local function validate_styles(package_path)
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: type")
|
||||
else
|
||||
-- Validate type enum
|
||||
local valid_types = {
|
||||
global = true,
|
||||
component = true,
|
||||
@@ -77,8 +89,7 @@ local function validate_styles(package_path)
|
||||
}
|
||||
if not valid_types[style.type] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has invalid type: " .. style.type ..
|
||||
" (must be: global, component, utility, or animation)")
|
||||
table.insert(result.messages, prefix .. " has invalid type: " .. style.type)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -107,20 +118,408 @@ local function validate_styles(package_path)
|
||||
table.insert(result.warnings, prefix .. " category should be a string")
|
||||
end
|
||||
|
||||
-- Validate CSS is not empty
|
||||
if style.css and style.css:match("^%s*$") then
|
||||
table.insert(result.warnings, prefix .. " has empty CSS content")
|
||||
end
|
||||
end
|
||||
|
||||
-- Summary
|
||||
if #styles == 0 then
|
||||
table.insert(result.warnings, "styles.json contains no style entries")
|
||||
else
|
||||
table.insert(result.messages, "Found " .. #styles .. " style entries")
|
||||
table.insert(result.messages, "V1 schema: Found " .. #styles .. " style entries")
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--- Validate V2 schema (object format)
|
||||
local function validate_styles_v2(styles, result)
|
||||
-- Validate schema_version
|
||||
if styles.schema_version then
|
||||
if type(styles.schema_version) ~= "string" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "schema_version must be a string")
|
||||
elseif not styles.schema_version:match("^%d+%.%d+%.%d+$") then
|
||||
table.insert(result.warnings, "schema_version should follow semantic versioning (e.g., 2.0.0)")
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate package field
|
||||
if styles.package then
|
||||
if type(styles.package) ~= "string" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "package must be a string")
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate tokens section
|
||||
if styles.tokens then
|
||||
if type(styles.tokens) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "tokens must be an object")
|
||||
else
|
||||
validate_tokens(styles.tokens, result)
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate selectors section
|
||||
if styles.selectors then
|
||||
if type(styles.selectors) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "selectors must be an array")
|
||||
else
|
||||
validate_selectors(styles.selectors, result)
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate effects section
|
||||
if styles.effects then
|
||||
if type(styles.effects) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "effects must be an array")
|
||||
else
|
||||
validate_effects(styles.effects, result)
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate appearance section
|
||||
if styles.appearance then
|
||||
if type(styles.appearance) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "appearance must be an array")
|
||||
else
|
||||
validate_appearance(styles.appearance, result)
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate layouts section
|
||||
if styles.layouts then
|
||||
if type(styles.layouts) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "layouts must be an array")
|
||||
else
|
||||
validate_layouts(styles.layouts, result)
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate transitions section
|
||||
if styles.transitions then
|
||||
if type(styles.transitions) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "transitions must be an array")
|
||||
else
|
||||
validate_transitions(styles.transitions, result)
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate rules section
|
||||
if styles.rules then
|
||||
if type(styles.rules) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "rules must be an array")
|
||||
else
|
||||
validate_rules(styles.rules, result)
|
||||
end
|
||||
end
|
||||
|
||||
-- Validate environments section
|
||||
if styles.environments then
|
||||
if type(styles.environments) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "environments must be an array")
|
||||
else
|
||||
validate_environments(styles.environments, result)
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(result.messages, "V2 schema validated")
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--- Validate tokens section
|
||||
function validate_tokens(tokens, result)
|
||||
if tokens.colors and type(tokens.colors) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "tokens.colors must be an object")
|
||||
end
|
||||
if tokens.spacing and type(tokens.spacing) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "tokens.spacing must be an object")
|
||||
end
|
||||
if tokens.typography and type(tokens.typography) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, "tokens.typography must be an object")
|
||||
end
|
||||
end
|
||||
|
||||
--- Validate selectors section
|
||||
function validate_selectors(selectors, result)
|
||||
local seen_ids = {}
|
||||
|
||||
for i, selector in ipairs(selectors) do
|
||||
local prefix = "Selector #" .. i
|
||||
|
||||
if not selector.id then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: id")
|
||||
else
|
||||
if seen_ids[selector.id] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has duplicate id: " .. selector.id)
|
||||
end
|
||||
seen_ids[selector.id] = true
|
||||
end
|
||||
|
||||
if not selector.predicate then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: predicate")
|
||||
elseif type(selector.predicate) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " predicate must be an object")
|
||||
else
|
||||
-- Validate predicate structure
|
||||
if not selector.predicate.targetType then
|
||||
table.insert(result.warnings, prefix .. " predicate missing targetType")
|
||||
end
|
||||
if selector.predicate.classes and type(selector.predicate.classes) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " predicate.classes must be an array")
|
||||
end
|
||||
if selector.predicate.states and type(selector.predicate.states) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " predicate.states must be an array")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Validate effects section
|
||||
function validate_effects(effects, result)
|
||||
local seen_ids = {}
|
||||
|
||||
for i, effect in ipairs(effects) do
|
||||
local prefix = "Effect #" .. i
|
||||
|
||||
if not effect.id then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: id")
|
||||
else
|
||||
if seen_ids[effect.id] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has duplicate id: " .. effect.id)
|
||||
end
|
||||
seen_ids[effect.id] = true
|
||||
end
|
||||
|
||||
if not effect.properties then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: properties")
|
||||
elseif type(effect.properties) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " properties must be an object")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Validate appearance section
|
||||
function validate_appearance(appearance, result)
|
||||
local seen_ids = {}
|
||||
|
||||
for i, app in ipairs(appearance) do
|
||||
local prefix = "Appearance #" .. i
|
||||
|
||||
if not app.id then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: id")
|
||||
else
|
||||
if seen_ids[app.id] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has duplicate id: " .. app.id)
|
||||
end
|
||||
seen_ids[app.id] = true
|
||||
end
|
||||
|
||||
if not app.layers then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: layers")
|
||||
elseif type(app.layers) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " layers must be an array")
|
||||
else
|
||||
for j, layer in ipairs(app.layers) do
|
||||
if not layer.type then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " layer #" .. j .. " missing type")
|
||||
else
|
||||
local valid_layer_types = {
|
||||
background = true,
|
||||
foreground = true,
|
||||
border = true,
|
||||
shadow = true,
|
||||
filter = true
|
||||
}
|
||||
if not valid_layer_types[layer.type] then
|
||||
table.insert(result.warnings, prefix .. " layer #" .. j .. " has unknown type: " .. layer.type)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Validate layouts section
|
||||
function validate_layouts(layouts, result)
|
||||
local seen_ids = {}
|
||||
|
||||
for i, layout in ipairs(layouts) do
|
||||
local prefix = "Layout #" .. i
|
||||
|
||||
if not layout.id then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: id")
|
||||
else
|
||||
if seen_ids[layout.id] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has duplicate id: " .. layout.id)
|
||||
end
|
||||
seen_ids[layout.id] = true
|
||||
end
|
||||
|
||||
if not layout.type then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: type")
|
||||
else
|
||||
local valid_layout_types = {
|
||||
flow = true,
|
||||
flex = true,
|
||||
grid = true,
|
||||
absolute = true,
|
||||
sticky = true
|
||||
}
|
||||
if not valid_layout_types[layout.type] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has invalid type: " .. layout.type)
|
||||
end
|
||||
end
|
||||
|
||||
if not layout.constraints then
|
||||
table.insert(result.warnings, prefix .. " missing constraints")
|
||||
elseif type(layout.constraints) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " constraints must be an object")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Validate transitions section
|
||||
function validate_transitions(transitions, result)
|
||||
local seen_ids = {}
|
||||
|
||||
for i, transition in ipairs(transitions) do
|
||||
local prefix = "Transition #" .. i
|
||||
|
||||
if not transition.id then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: id")
|
||||
else
|
||||
if seen_ids[transition.id] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has duplicate id: " .. transition.id)
|
||||
end
|
||||
seen_ids[transition.id] = true
|
||||
end
|
||||
|
||||
if not transition.trigger then
|
||||
table.insert(result.warnings, prefix .. " missing trigger")
|
||||
end
|
||||
|
||||
if not transition.properties then
|
||||
table.insert(result.warnings, prefix .. " missing properties")
|
||||
elseif type(transition.properties) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " properties must be an array")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Validate rules section (the cascade layer)
|
||||
function validate_rules(rules, result)
|
||||
local seen_ids = {}
|
||||
|
||||
for i, rule in ipairs(rules) do
|
||||
local prefix = "Rule #" .. i
|
||||
|
||||
if not rule.id then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: id")
|
||||
else
|
||||
if seen_ids[rule.id] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has duplicate id: " .. rule.id)
|
||||
end
|
||||
seen_ids[rule.id] = true
|
||||
end
|
||||
|
||||
if not rule.selector then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: selector")
|
||||
elseif type(rule.selector) ~= "string" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " selector must be a string reference")
|
||||
end
|
||||
|
||||
if not rule.priority then
|
||||
table.insert(result.warnings, prefix .. " missing priority (cascade resolution)")
|
||||
elseif type(rule.priority) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " priority must be an object")
|
||||
else
|
||||
-- Validate priority structure
|
||||
if not rule.priority.importance then
|
||||
table.insert(result.warnings, prefix .. " priority missing importance")
|
||||
end
|
||||
if not rule.priority.specificity then
|
||||
table.insert(result.warnings, prefix .. " priority missing specificity")
|
||||
elseif type(rule.priority.specificity) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " priority.specificity must be an object")
|
||||
end
|
||||
end
|
||||
|
||||
if rule.enabled ~= nil and type(rule.enabled) ~= "boolean" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " enabled must be a boolean")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Validate environments section
|
||||
function validate_environments(environments, result)
|
||||
local seen_ids = {}
|
||||
|
||||
for i, env in ipairs(environments) do
|
||||
local prefix = "Environment #" .. i
|
||||
|
||||
if not env.id then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: id")
|
||||
else
|
||||
if seen_ids[env.id] then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " has duplicate id: " .. env.id)
|
||||
end
|
||||
seen_ids[env.id] = true
|
||||
end
|
||||
|
||||
if not env.conditions then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " missing required field: conditions")
|
||||
elseif type(env.conditions) ~= "table" then
|
||||
result.success = false
|
||||
table.insert(result.messages, prefix .. " conditions must be an object")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return validate_styles
|
||||
|
||||
Reference in New Issue
Block a user