@@ -48,41 +48,95 @@ const decodeHTML = (str) => {
48
48
. replace ( / & # 0 3 9 ; / g, "'" ) ;
49
49
} ;
50
50
51
- const htmlWrapper = ( htmlString , layout ) => {
52
- return `<!DOCTYPE html><html><head><style>html, body {height:100%} body {box-sizing: border-box; margin: 0; padding:0.5rem; ${ layout } }</style><script src="https://cdn.shopify.com/shopifycloud/polaris.js"></script></head><body>${ decodeHTML (
51
+ const composeStyles = ( ...styles ) => {
52
+ return styles
53
+ . filter ( Boolean )
54
+ . map ( ( style ) => style . trim ( ) )
55
+ . filter ( ( style ) => style . length > 0 )
56
+ . join ( ' ' ) ;
57
+ } ;
58
+
59
+ /**
60
+ * Converts CSS style object to CSS string
61
+ * @param {string | object } styles - CSS string or object
62
+ * @returns {string } CSS string
63
+ */
64
+ const stylesToString = ( styles ) => {
65
+ if ( typeof styles === 'string' ) {
66
+ return styles ;
67
+ }
68
+ if ( typeof styles === 'object' && styles !== null ) {
69
+ return Object . entries ( styles )
70
+ . map ( ( [ property , value ] ) => {
71
+ // Convert camelCase to kebab-case
72
+ const kebabProperty = property . replace (
73
+ / [ A - Z ] / g,
74
+ ( match ) => `-${ match . toLowerCase ( ) } ` ,
75
+ ) ;
76
+ return `${ kebabProperty } : ${ value } ` ;
77
+ } )
78
+ . join ( '; ' ) ;
79
+ }
80
+ return '' ;
81
+ } ;
82
+
83
+ const htmlWrapper = ( htmlString , layoutStyles = '' , customStyles = '' ) => {
84
+ const baseStyles = 'box-sizing: border-box; margin: 0; padding: 0.5rem;' ;
85
+ const customStylesString = stylesToString ( customStyles ) ;
86
+ const composedStyles = composeStyles (
87
+ baseStyles ,
88
+ layoutStyles ,
89
+ customStylesString ,
90
+ ) ;
91
+
92
+ return `<!DOCTYPE html><html><head><style>html, body {height:100%} body {${ composedStyles } }</style><script src="https://cdn.shopify.com/shopifycloud/polaris.js"></script></head><body>${ decodeHTML (
53
93
htmlString ,
54
94
) } </body></html>`;
55
95
} ;
56
96
97
+ const createTemplate = ( {
98
+ layoutStyles,
99
+ wrapperElement = null ,
100
+ wrapperAttributes = '' ,
101
+ } ) => {
102
+ return ( htmlString , customStyles = '' ) => {
103
+ const wrappedHtml = wrapperElement
104
+ ? `<${ wrapperElement } ${
105
+ wrapperAttributes ? ` ${ wrapperAttributes } ` : ''
106
+ } >${ htmlString } </${ wrapperElement } >`
107
+ : htmlString ;
108
+
109
+ return htmlWrapper ( wrappedHtml , layoutStyles , stylesToString ( customStyles ) ) ;
110
+ } ;
111
+ } ;
112
+
57
113
const templates = {
58
- default : ( htmlString ) =>
59
- htmlWrapper ( htmlString , 'display: grid; place-items: center; gap: 0.5rem;' ) ,
60
- alignStart : ( htmlString ) =>
61
- htmlWrapper (
62
- `<div>${ htmlString } </div>` ,
63
- 'display: grid; place-items: start center; gap: 0.5rem;' ,
64
- ) ,
65
- wrapped : ( htmlString ) =>
66
- htmlWrapper (
67
- `<div>${ htmlString } </div>` ,
68
- 'display: grid; place-items: center; gap: 0.5rem;' ,
69
- ) ,
70
- inline : ( htmlString ) =>
71
- htmlWrapper (
72
- htmlString ,
114
+ default : createTemplate ( {
115
+ layoutStyles : 'display: grid; place-items: center; gap: 0.5rem;' ,
116
+ } ) ,
117
+ alignStart : createTemplate ( {
118
+ layoutStyles : 'display: grid; place-items: start center; gap: 0.5rem;' ,
119
+ wrapperElement : 'div' ,
120
+ } ) ,
121
+ wrapped : createTemplate ( {
122
+ layoutStyles : 'display: grid; place-items: center; gap: 0.5rem;' ,
123
+ wrapperElement : 'div' ,
124
+ } ) ,
125
+ inline : createTemplate ( {
126
+ layoutStyles :
73
127
'display: flex; justify-content: center; align-items: center; gap: 0.5rem;' ,
74
- ) ,
75
- section : ( htmlString ) =>
76
- htmlWrapper (
77
- `< s-section padding="none"> ${ htmlString } </s-section>` ,
78
- 'display: grid; place-items: center; background: #F1F1F1 ',
79
- ) ,
80
- page : ( htmlString ) =>
81
- htmlWrapper (
82
- htmlString ,
83
- 'display: grid; place-items: center; background: #F1F1F1;' ,
84
- ) ,
85
- none : ( htmlString ) => htmlWrapper ( htmlString , 'padding: 0' ) ,
128
+ } ) ,
129
+ section : createTemplate ( {
130
+ layoutStyles : 'display: grid; place-items: center; background: #F1F1F1' ,
131
+ wrapperElement : ' s-section' ,
132
+ wrapperAttributes : 'padding="none" ',
133
+ } ) ,
134
+ page : createTemplate ( {
135
+ layoutStyles : 'display: grid; place-items: center; background: #F1F1F1;' ,
136
+ } ) ,
137
+ none : createTemplate ( {
138
+ layoutStyles : 'padding: 0' ,
139
+ } ) ,
86
140
} ;
87
141
88
142
const transformJson = async ( filePath , isExtensions ) => {
@@ -124,8 +178,8 @@ const transformJson = async (filePath, isExtensions) => {
124
178
125
179
const previewHTML =
126
180
tab . layout && tab . layout in templates
127
- ? templates [ tab . layout ] ( tab . code )
128
- : templates . default ( tab . code ) ;
181
+ ? templates [ tab . layout ] ( tab . code , tab . customStyles )
182
+ : templates . default ( tab . code , tab . customStyles ) ;
129
183
130
184
newTabs . push (
131
185
{ code : tab . code , language : 'html' } ,
0 commit comments