932932 padding : calc (var (--spacing ) / 4 );
933933 }
934934
935+ /* Validation Errors Styles */
936+ .validation-errors {
937+ background-color : # f8d7da ;
938+ border : 1px solid # f5c2c7 ;
939+ border-radius : 4px ;
940+ padding : calc (var (--spacing ) / 2 );
941+ margin-bottom : var (--spacing );
942+ display : none;
943+ }
944+
945+ .validation-errors .visible {
946+ display : block;
947+ }
948+
949+ .validation-errors-title {
950+ font-weight : 600 ;
951+ color : # 842029 ;
952+ margin-bottom : calc (var (--spacing ) / 4 );
953+ display : flex;
954+ align-items : center;
955+ gap : calc (var (--spacing ) / 2 );
956+ font-size : 0.85rem ;
957+ }
958+
959+ .validation-errors-list {
960+ list-style : none;
961+ padding : 0 ;
962+ margin : 0 ;
963+ max-height : 100px ;
964+ overflow-y : auto;
965+ }
966+
967+ .validation-errors-list li {
968+ font-size : 0.8rem ;
969+ color : # 842029 ;
970+ padding : calc (var (--spacing ) / 4 ) 0 ;
971+ border-bottom : 1px solid rgba (132 , 32 , 41 , 0.2 );
972+ }
973+
974+ .validation-errors-list li : last-child {
975+ border-bottom : none;
976+ }
977+
935978 /* Validation Warnings Styles */
936979 .validation-warnings {
937980 background-color : # fff3cd ;
@@ -1167,6 +1210,15 @@ <h4 class="collections-group-title">Extended Settings</h4>
11671210 </ div >
11681211 </ div >
11691212
1213+ <!-- Validation Errors -->
1214+ < div class ="validation-errors " id ="validation-errors ">
1215+ < div class ="validation-errors-title ">
1216+ Validation Errors
1217+ </ div >
1218+ < ul class ="validation-errors-list " id ="validation-errors-list ">
1219+ </ ul >
1220+ </ div >
1221+
11701222 <!-- Validation Warnings -->
11711223 < div class ="validation-warnings " id ="validation-warnings ">
11721224 < div class ="validation-warnings-title ">
@@ -1182,6 +1234,7 @@ <h4 class="collections-group-title">Extended Settings</h4>
11821234
11831235 < div class ="button-row ">
11841236 < button id ="export " type ="button "> Export Variables</ button >
1237+ < button id ="validate-export " type ="button " class ="secondary " style ="display:none; "> Validate Schema</ button >
11851238 < button id ="download " type ="button "> Download theme.json</ button >
11861239 </ div >
11871240 < div id ="files-container ">
@@ -1327,66 +1380,80 @@ <h3 class="modal-title">Customize Color Presets (Selected Collections)</h3>
13271380
13281381 currentFiles = pluginMessage . files ;
13291382
1330- // Handle validation warnings if present
1383+ // Handle validation errors and warnings if present
1384+ const validationErrors = pluginMessage . errors || [ ] ;
13311385 validationWarnings = pluginMessage . warnings || [ ] ;
1386+ displayValidationErrors ( validationErrors ) ;
13321387 displayValidationWarnings ( validationWarnings ) ;
1333-
1388+
1389+ // Show validate button now that we have export data
1390+ document . getElementById ( "validate-export" ) . style . display = "inline-block" ;
1391+
13341392 // Clear the files container
13351393 const filesContainer = document . getElementById ( 'files-container' ) ;
13361394 filesContainer . innerHTML = '' ;
1337-
1395+
13381396 // Add each file to the container
13391397 currentFiles . forEach ( ( file , index ) => {
13401398 const { fileName, body } = file ;
13411399 const fileContent = JSON . stringify ( body , null , 2 ) ;
1342-
1400+
13431401 // Create file container
13441402 const fileContainer = document . createElement ( 'div' ) ;
13451403 fileContainer . className = 'file-container' ;
1346-
1404+
13471405 // Create file header with name and actions
13481406 const fileHeader = document . createElement ( 'div' ) ;
13491407 fileHeader . className = 'file-header' ;
1350-
1408+
13511409 const fileName2 = document . createElement ( 'div' ) ;
13521410 fileName2 . className = 'file-name' ;
13531411 fileName2 . textContent = fileName ;
1354-
1412+
13551413 const fileActions = document . createElement ( 'div' ) ;
13561414 fileActions . className = 'file-actions' ;
1357-
1415+
13581416 const copyButton = document . createElement ( 'button' ) ;
13591417 copyButton . className = 'copy-button' ;
13601418 copyButton . textContent = 'Copy' ;
13611419 copyButton . onclick = ( ) => copyToClipboard ( index ) ;
1362-
1420+
13631421 fileActions . appendChild ( copyButton ) ;
13641422 fileHeader . appendChild ( fileName2 ) ;
13651423 fileHeader . appendChild ( fileActions ) ;
1366-
1424+
13671425 // Create textarea for the file content
13681426 const textarea = document . createElement ( 'textarea' ) ;
13691427 textarea . readOnly = true ;
13701428 textarea . id = `file-content-${ index } ` ;
13711429 textarea . value = fileContent ;
1372-
1430+
13731431 // Assemble the file container
13741432 fileContainer . appendChild ( fileHeader ) ;
13751433 fileContainer . appendChild ( textarea ) ;
1376-
1434+
13771435 // Add to files container
13781436 filesContainer . appendChild ( fileContainer ) ;
13791437 } ) ;
1380-
1438+
13811439 // Show download button if we have files
13821440 if ( currentFiles . length > 0 ) {
13831441 document . getElementById ( "download" ) . style . display = "block" ;
13841442 // Update button text to indicate it's a zip download if multiple files
13851443 const downloadBtn = document . getElementById ( "download" ) ;
1386- downloadBtn . textContent = currentFiles . length > 1
1387- ? `Download Theme Files (${ currentFiles . length } files)`
1444+ downloadBtn . textContent = currentFiles . length > 1
1445+ ? `Download Theme Files (${ currentFiles . length } files)`
13881446 : "Download theme.json" ;
13891447 }
1448+ } else if ( pluginMessage . type === "VALIDATE_EXPORT_RESULT" ) {
1449+ if ( pluginMessage . error ) {
1450+ displayValidationErrors ( [ pluginMessage . error ] ) ;
1451+ return ;
1452+ }
1453+
1454+ const validation = pluginMessage . validation ;
1455+ displayValidationErrors ( validation . errors || [ ] ) ;
1456+ displayValidationWarnings ( validation . warnings || [ ] ) ;
13901457 }
13911458 } ;
13921459
@@ -1598,7 +1665,31 @@ <h3 class="modal-title">Customize Color Presets (Selected Collections)</h3>
15981665 toggleIcon . classList . toggle ( 'collapsed' ) ;
15991666 } ) ;
16001667
1601- // Validation warnings functionality
1668+ // Validation display functionality
1669+ function displayValidationErrors ( errors ) {
1670+ const errorsContainer = document . getElementById ( 'validation-errors' ) ;
1671+ const errorsList = document . getElementById ( 'validation-errors-list' ) ;
1672+
1673+ if ( ! errors || errors . length === 0 ) {
1674+ errorsContainer . classList . remove ( 'visible' ) ;
1675+ errorsList . innerHTML = '' ;
1676+ return ;
1677+ }
1678+
1679+ errorsContainer . classList . add ( 'visible' ) ;
1680+ const errorsTitle = errorsContainer . querySelector ( '.validation-errors-title' ) ;
1681+ errorsTitle . textContent = errors . length === 1
1682+ ? '1 Validation Error'
1683+ : errors . length + ' Validation Errors' ;
1684+
1685+ errorsList . innerHTML = '' ;
1686+ errors . forEach ( error => {
1687+ const li = document . createElement ( 'li' ) ;
1688+ li . textContent = error ;
1689+ errorsList . appendChild ( li ) ;
1690+ } ) ;
1691+ }
1692+
16021693 function displayValidationWarnings ( warnings ) {
16031694 const warningsContainer = document . getElementById ( 'validation-warnings' ) ;
16041695 const warningsList = document . getElementById ( 'validation-warnings-list' ) ;
@@ -1610,15 +1701,35 @@ <h3 class="modal-title">Customize Color Presets (Selected Collections)</h3>
16101701 }
16111702
16121703 warningsContainer . classList . add ( 'visible' ) ;
1613- warningsList . innerHTML = '' ;
1704+ const warningsTitle = warningsContainer . querySelector ( '.validation-warnings-title' ) ;
1705+ warningsTitle . textContent = warnings . length === 1
1706+ ? '1 Validation Warning'
1707+ : warnings . length + ' Validation Warnings' ;
16141708
1709+ warningsList . innerHTML = '' ;
16151710 warnings . forEach ( warning => {
16161711 const li = document . createElement ( 'li' ) ;
16171712 li . textContent = warning ;
16181713 warningsList . appendChild ( li ) ;
16191714 } ) ;
16201715 }
16211716
1717+ // Standalone validate button
1718+ document . getElementById ( 'validate-export' ) . addEventListener ( 'click' , ( ) => {
1719+ if ( ! currentFiles || currentFiles . length === 0 ) return ;
1720+
1721+ // Find the theme.json file
1722+ const themeFile = currentFiles . find ( f => f . fileName === 'theme.json' ) ;
1723+ if ( ! themeFile ) return ;
1724+
1725+ parent . postMessage ( {
1726+ pluginMessage : {
1727+ type : "VALIDATE_EXPORT" ,
1728+ themeJson : themeFile . body
1729+ }
1730+ } , "*" ) ;
1731+ } ) ;
1732+
16221733 // Color customization functionality
16231734 const colorPresetsCheckbox = document . getElementById ( "generate-color-presets" ) ;
16241735 const customizeButton = document . getElementById ( "customize-colors" ) ;
0 commit comments