jsharmony-cms 1.3.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/clientjs/component/componentModel/dataModelTemplate_gridPreview.js +3 -1
- package/clientjs/component/templateRenderer.js +2 -0
- package/clientjs/jsHarmonyCMS.ComponentManager.js +24 -0
- package/clientjs/jsHarmonyCMS.Editor.js +3 -0
- package/doc/site_config.json +28 -3
- package/jsHarmonyCMSConfig.js +1 -1
- package/models/Dashboard_BranchOverview.css +3 -0
- package/models/Dashboard_BranchOverview.ejs +1 -1
- package/models/_funcs.branch.js +2 -2
- package/models/_funcs.component.js +2 -0
- package/models/_funcs.deploy.js +60 -14
- package/models/_funcs.deployment_target.js +5 -0
- package/models/_funcs.media.js +23 -13
- package/models/_funcs.page.js +12 -6
- package/models/_funcs.search.js +12 -1
- package/models/_funcs.template.js +105 -0
- package/models/_funcs.validate.js +17 -17
- package/package.json +3 -3
- package/public/js/jsHarmonyCMS.js +32 -1
- package/views/jsh_cms_editor.css.ejs +24 -0
- package/views/jsh_cms_editor.ejs +3 -0
|
@@ -115,7 +115,9 @@ DataModelTemplate_GridPreview.prototype.buildTemplate = function(componentTempla
|
|
|
115
115
|
model.oncommit = '_this.onCommit(xmodel, rowid, callback);';
|
|
116
116
|
model.ejs = '';
|
|
117
117
|
model.sort = { [this._sequenceFieldName]: 'asc' };
|
|
118
|
-
model.oninit =
|
|
118
|
+
model.oninit = [
|
|
119
|
+
"jsh.$root('.xform'+xmodel.class).before('<div class=\"dataGridEditor_instructions\"><span style=\"font-size:1.3em;position:relative;top:1px;margin-right:2px;margin-left:4px;\">🛈</span> Add, edit, and re-order items using the icons <span class=\"dataGridEditor_instructions_doubleClick\">:: Double-click to edit</span></div>');",
|
|
120
|
+
].join(' ');
|
|
119
121
|
model.rowclass = "<%=xejs.iif(rowid==0,'first')%>";
|
|
120
122
|
model.tableclass = ((model.tableclass||'')+' '+(componentConfig&&componentConfig.options&&componentConfig.options.component_preview_size=='collapse'?'jsharmony_cms_component_preview_collapse':'jsharmony_cms_component_preview_expand')).trim();
|
|
121
123
|
this._jsh.XPage.ParseModelDefinition(model, null, null, { ignoreErrors: true });
|
|
@@ -111,6 +111,8 @@ TemplateRenderer.render = function(config, type, jsh, cms, componentConfig, addi
|
|
|
111
111
|
isInEditor: true,
|
|
112
112
|
isInPageEditor: true,
|
|
113
113
|
isInComponentEditor: ((type=='gridRowDataPreview') || (type=='gridItemPreview')),
|
|
114
|
+
componentRenderClass: 'jsharmony_cms_componentRender_'+jsh.XExt.escapeCSSClass((componentConfig&&componentConfig.id)||'')+'_'+cms.componentManager.getUniqueId().toString(),
|
|
115
|
+
getMediaThumbnails: function(url){ return cms.componentManager.getMediaThumbnails(url); },
|
|
114
116
|
renderPlaceholder: renderPlaceholder,
|
|
115
117
|
}, additionalRenderParams));
|
|
116
118
|
|
|
@@ -34,6 +34,8 @@ exports = module.exports = function(jsh, cms){
|
|
|
34
34
|
this.containerlessComponents = {};
|
|
35
35
|
this.cntContainerlessComponents = 0;
|
|
36
36
|
|
|
37
|
+
var maxUniqueId = 0;
|
|
38
|
+
|
|
37
39
|
this.load = function(onError){
|
|
38
40
|
_this.loadSystemComponentTemplates(onError);
|
|
39
41
|
}
|
|
@@ -375,6 +377,8 @@ exports = module.exports = function(jsh, cms){
|
|
|
375
377
|
isInEditor: true,
|
|
376
378
|
isInPageEditor: false,
|
|
377
379
|
isInComponentEditor: false,
|
|
380
|
+
componentRenderClass: 'jsharmony_cms_componentRender_'+XExt.escapeCSSClass((component&&component.id)||'')+'_'+cms.componentManager.getUniqueId().toString(),
|
|
381
|
+
getMediaThumbnails: function(url){ return cms.componentManager.getMediaThumbnails(url); },
|
|
378
382
|
items: data.items,
|
|
379
383
|
item: data.item,
|
|
380
384
|
component: properties,
|
|
@@ -401,4 +405,24 @@ exports = module.exports = function(jsh, cms){
|
|
|
401
405
|
}
|
|
402
406
|
return rslt;
|
|
403
407
|
}
|
|
408
|
+
|
|
409
|
+
this.getUniqueId = function(){ return ++maxUniqueId; }
|
|
410
|
+
|
|
411
|
+
this.getMediaThumbnails = function(url){
|
|
412
|
+
if(!cms.site_config || !cms.site_config.media_thumbnails) return {};
|
|
413
|
+
if(!url || (url.indexOf('#@JSHCMS') < 0)) return {};
|
|
414
|
+
|
|
415
|
+
var urlparts = document.createElement('a');
|
|
416
|
+
urlparts.href = url;
|
|
417
|
+
var patharr = (urlparts.pathname||'').split('/');
|
|
418
|
+
var rslt = {};
|
|
419
|
+
if(((urlparts.pathname||'').indexOf('/_funcs/media/')==0) && (patharr.length>=4)){
|
|
420
|
+
for(var thumbnail_id in cms.site_config.media_thumbnails){
|
|
421
|
+
if((patharr.length >= 5) && patharr[4]) patharr[4] = thumbnail_id;
|
|
422
|
+
else patharr.splice(4,0,thumbnail_id);
|
|
423
|
+
rslt[thumbnail_id] = urlparts.protocol + '//' + urlparts.host + patharr.join('/') + (urlparts.search||'') + (urlparts.hash||'');
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return rslt;
|
|
427
|
+
}
|
|
404
428
|
}
|
|
@@ -83,6 +83,9 @@ exports = module.exports = function(jsh, cms, toolbarContainer){
|
|
|
83
83
|
],
|
|
84
84
|
contextmenu: 'jsharmonycmscomponentcontextmenu link linkchecker image imagetools table spellchecker configurepermanentpen',
|
|
85
85
|
toolbar: 'formatselect | backcolor forecolor | bold italic underline | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image charmapmaterialicons table fullscreen | jsHarmonyCmsWebSnippet | jsHarmonyCmsComponent | jsHarmonyCmsView | jsHarmonyCmsEndEdit',
|
|
86
|
+
mobile: {
|
|
87
|
+
toolbar_mode: 'floating',
|
|
88
|
+
},
|
|
86
89
|
removed_menuitems: 'newdocument',
|
|
87
90
|
image_advtab: true,
|
|
88
91
|
menu: {
|
package/doc/site_config.json
CHANGED
|
@@ -13,11 +13,36 @@
|
|
|
13
13
|
"template_variables": { // Default values for Template Variables
|
|
14
14
|
"key": "value"
|
|
15
15
|
},
|
|
16
|
+
|
|
17
|
+
//Media thumbnail configuration
|
|
16
18
|
"media_thumbnails": {
|
|
19
|
+
"thumbnail_id": {
|
|
20
|
+
//(Optional) Resize thumbnail to fit within target width and height
|
|
21
|
+
"resize": [150, 150], // [width, height]
|
|
22
|
+
|
|
23
|
+
//(Optional) Crop thumbnail to target width and height
|
|
24
|
+
"crop": [150, 150], // [width, height]
|
|
25
|
+
|
|
26
|
+
//(Optional) Resample thumbnail to target format (jpg, png, gif, tif)
|
|
27
|
+
"format": "jpg",
|
|
28
|
+
|
|
29
|
+
//(Optional) Export thumbnail on publish, as filename.thumbnail_id.extension
|
|
30
|
+
"export": true,
|
|
31
|
+
|
|
32
|
+
//(Optional) Add as an srcset responsive breakpoint to IMG tags in published content
|
|
33
|
+
// If set to a string, the value will be used as the srcset condition, ex. "1x" "2x" "2048w"
|
|
34
|
+
// If set to true, the thumbnail width will be used as the srcset condition, ex "150w"
|
|
35
|
+
"responsive": true,
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
//Default Thumbnails
|
|
17
39
|
"file_tile": { "resize": [150, 150], "format": "jpg" },
|
|
18
40
|
"file_preview": { "resize": [300, 300], "format": "jpg" },
|
|
19
|
-
"small": { "resize": [512, 384]
|
|
20
|
-
"medium": { "resize": [1024, 768]
|
|
21
|
-
"large": { "resize": [2048, 1538] }
|
|
41
|
+
"small": { "resize": [512, 384] },
|
|
42
|
+
"medium": { "resize": [1024, 768] },
|
|
43
|
+
"large": { "resize": [2048, 1538] },
|
|
44
|
+
|
|
45
|
+
//(Optional) Set a maximum image size for uploaded media
|
|
46
|
+
"maximum": { "resize": [2048, 1538] }
|
|
22
47
|
}
|
|
23
48
|
}
|
package/jsHarmonyCMSConfig.js
CHANGED
|
@@ -58,7 +58,7 @@ function jsHarmonyCMSConfig(){
|
|
|
58
58
|
serverHttpsCa: undefined, // path/to/https-ca.pem
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
this.media_thumbnails = {
|
|
61
|
+
this.media_thumbnails = { //Media thumbnail configuration. See site_config.json for options
|
|
62
62
|
file_tile: { resize: [150, 150], format: "jpg" },
|
|
63
63
|
file_preview: { resize: [300, 300], format: "jpg" },
|
|
64
64
|
small: { resize: [512, 384] },
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<%% } %%>
|
|
31
31
|
<%% _.each(cur_branch && branch_data, function(branch_item){ if(branch_item.code_val=='branch') return; %%>
|
|
32
32
|
<tr>
|
|
33
|
-
<th valign="bottom">  
|
|
33
|
+
<th valign="bottom"> <a href="<%%=jsh.globalparams.branch_items[branch_item.code_val].editor_url%%>"><%%=branch_item.code_txt%%></a></th>
|
|
34
34
|
<td valign="bottom">
|
|
35
35
|
<%%=branch_item.cnt%%>
|
|
36
36
|
</td>
|
package/models/_funcs.branch.js
CHANGED
|
@@ -629,14 +629,14 @@ module.exports = exports = function(module, funcs){
|
|
|
629
629
|
//Replace URLs
|
|
630
630
|
function replaceURLs(content, options){
|
|
631
631
|
var rslt = funcs.replaceBranchURLs(content, _.extend({ replaceComponents: true }, options, {
|
|
632
|
-
getMediaURL: function(media_key, _branchData, getLinkContent){
|
|
632
|
+
getMediaURL: function(media_key, thumbnail_id, _branchData, getLinkContent){
|
|
633
633
|
var orig_media_key = media_key;
|
|
634
634
|
var media_file_id = media_key;
|
|
635
635
|
if(branchData.media_mapping[orig_media_key]){
|
|
636
636
|
media_key = branchData.media_mapping[orig_media_key].new_media_id;
|
|
637
637
|
media_file_id = branchData.media_mapping[orig_media_key].new_media_file_id || media_key;
|
|
638
638
|
}
|
|
639
|
-
return branchData._baseurl+'_funcs/media/'+media_key+'/?media_file_id='+media_file_id+'#@JSHCMS';
|
|
639
|
+
return branchData._baseurl+'_funcs/media/'+media_key+(thumbnail_id?'/'+thumbnail_id:'')+'/?media_file_id='+media_file_id+'#@JSHCMS';
|
|
640
640
|
},
|
|
641
641
|
getPageURL: function(page_key){
|
|
642
642
|
var orig_page_key = page_key;
|
|
@@ -659,9 +659,11 @@ module.exports = exports = function(module, funcs){
|
|
|
659
659
|
isInEditor: false,
|
|
660
660
|
isInPageEditor: false,
|
|
661
661
|
isInComponentEditor: false,
|
|
662
|
+
componentRenderClass: 'jsharmony_cms_componentRender_'+Helper.escapeCSSClass((renderOptions.templateName)||'')+'_'+((branchData && branchData.component_getUniqueId && branchData.component_getUniqueId())||'').toString(),
|
|
662
663
|
items: [],
|
|
663
664
|
item: {},
|
|
664
665
|
component: properties,
|
|
666
|
+
getMediaThumbnails: function(url){ return funcs.getMediaThumbnails(url, branchData); },
|
|
665
667
|
renderPlaceholder: function(){ return ''; },
|
|
666
668
|
renderTemplate: function(locals, templateName, items){
|
|
667
669
|
if(!items || (_.isArray(items) && !items.length)) return '';
|
package/models/_funcs.deploy.js
CHANGED
|
@@ -119,17 +119,19 @@ module.exports = exports = function(module, funcs){
|
|
|
119
119
|
return page_fpath;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
exports.getMediaRelativePath = function(media, publish_params,
|
|
122
|
+
exports.getMediaRelativePath = function(media, publish_params, thumbnail_id, thumbnail_config){
|
|
123
123
|
var media_fpath = media.media_path||'';
|
|
124
124
|
if(!media_fpath) return '';
|
|
125
125
|
while(media_fpath.substr(0,1)=='/') media_fpath = media_fpath.substr(1);
|
|
126
126
|
|
|
127
|
-
if(
|
|
127
|
+
if(thumbnail_id){
|
|
128
128
|
var lastDot = media_fpath.lastIndexOf('.');
|
|
129
129
|
var lastSlash = Math.max(media_fpath.lastIndexOf('/'),media_fpath.lastIndexOf('\\'));
|
|
130
|
-
if((lastDot < 0) || (lastDot < lastSlash)) media_fpath += '.'+
|
|
130
|
+
if((lastDot < 0) || (lastDot < lastSlash)) media_fpath += '.'+thumbnail_id;
|
|
131
131
|
else {
|
|
132
|
-
media_fpath = media_fpath.substr(0, lastDot) +
|
|
132
|
+
media_fpath = media_fpath.substr(0, lastDot) +
|
|
133
|
+
'.' + thumbnail_id +
|
|
134
|
+
((thumbnail_config && thumbnail_config.format) ? '.' + thumbnail_config.format : media_fpath.substr(lastDot));
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
@@ -142,6 +144,36 @@ module.exports = exports = function(module, funcs){
|
|
|
142
144
|
return media_fpath;
|
|
143
145
|
}
|
|
144
146
|
|
|
147
|
+
exports.getMediaThumbnails = function(url, branchData){
|
|
148
|
+
if(!branchData || !branchData.media_items || !branchData.site_config || !branchData.site_config.media_thumbnails) return {};
|
|
149
|
+
if(!url || (url.indexOf('#@JSHCMS') < 0)) return {};
|
|
150
|
+
var urlparts = null;
|
|
151
|
+
try{
|
|
152
|
+
urlparts = urlparser.parse(url, true);
|
|
153
|
+
}
|
|
154
|
+
catch(ex){
|
|
155
|
+
return {};
|
|
156
|
+
}
|
|
157
|
+
if(!urlparts.pathname) return {};
|
|
158
|
+
var patharr = (urlparts.pathname||'').split('/');
|
|
159
|
+
|
|
160
|
+
var rslt = {};
|
|
161
|
+
if((urlparts.pathname.indexOf('/_funcs/media/')==0) && (patharr.length>=4)){
|
|
162
|
+
var media_key = patharr[3];
|
|
163
|
+
if(!(media_key in branchData.media_items)) return {};
|
|
164
|
+
var media = branchData.media_items[media_key];
|
|
165
|
+
for(var thumbnail_id in branchData.site_config.media_thumbnails){
|
|
166
|
+
var thumbnail_config = branchData.site_config.media_thumbnails[thumbnail_id];
|
|
167
|
+
if(!thumbnail_config || !thumbnail_config.export) continue;
|
|
168
|
+
if(!_.includes(['.jpg','.jpeg','.tif','.tiff','.png','.gif','.svg'], media.media_ext)) continue;
|
|
169
|
+
if((patharr.length >= 5) && patharr[4]) patharr[4] = thumbnail_id;
|
|
170
|
+
else patharr.splice(4,0,thumbnail_id);
|
|
171
|
+
rslt[thumbnail_id] = urlparts.protocol + '//' + urlparts.host + patharr.join('/') + (urlparts.search||'') + (urlparts.hash||'');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return rslt;
|
|
175
|
+
}
|
|
176
|
+
|
|
145
177
|
exports.downloadLocalTemplates = function(branchData, templates, template_html, options, download_cb){
|
|
146
178
|
options = _.extend({ templateType: 'PAGE', exportTemplates: {} }, options);
|
|
147
179
|
|
|
@@ -592,6 +624,8 @@ module.exports = exports = function(module, funcs){
|
|
|
592
624
|
deployment.publish_params = publish_params;
|
|
593
625
|
|
|
594
626
|
//Branch Data
|
|
627
|
+
var component_maxUniqueId = 0;
|
|
628
|
+
var component_maxUniqueIdSalt = crypto.randomBytes(16).toString('hex');
|
|
595
629
|
var branchData = {
|
|
596
630
|
publish_params: publish_params,
|
|
597
631
|
template_variables: template_variables,
|
|
@@ -612,8 +646,10 @@ module.exports = exports = function(module, funcs){
|
|
|
612
646
|
component_templates: null,
|
|
613
647
|
component_template_html: {},
|
|
614
648
|
component_export_template_html: {},
|
|
649
|
+
component_getUniqueId: function(){ return crypto.createHash('md5').update(component_maxUniqueIdSalt+'.'+(++component_maxUniqueId).toString()).digest("hex"); },
|
|
615
650
|
|
|
616
651
|
media_keys: {},
|
|
652
|
+
media_items: {},
|
|
617
653
|
|
|
618
654
|
menus: {},
|
|
619
655
|
menu_template_html: {},
|
|
@@ -1289,7 +1325,7 @@ module.exports = exports = function(module, funcs){
|
|
|
1289
1325
|
|
|
1290
1326
|
//Get list of all media_keys
|
|
1291
1327
|
var sql = 'select \
|
|
1292
|
-
m.media_key,media_file_id,media_path \
|
|
1328
|
+
m.media_key,media_file_id,media_path,media_width,media_height,media_ext \
|
|
1293
1329
|
from '+(module.schema?module.schema+'.':'')+'media m \
|
|
1294
1330
|
inner join '+(module.schema?module.schema+'.':'')+'branch_media bm on bm.media_id = m.media_id\
|
|
1295
1331
|
inner join '+(module.schema?module.schema+'.':'')+'deployment d on d.branch_id = bm.branch_id and d.deployment_id=@deployment_id\
|
|
@@ -1311,7 +1347,10 @@ module.exports = exports = function(module, funcs){
|
|
|
1311
1347
|
}
|
|
1312
1348
|
catch(ex){ }
|
|
1313
1349
|
|
|
1314
|
-
if(media_urlpath)
|
|
1350
|
+
if(media_urlpath){
|
|
1351
|
+
branchData.media_keys[media.media_key] = media_urlpath;
|
|
1352
|
+
branchData.media_items[media.media_key] = media;
|
|
1353
|
+
}
|
|
1315
1354
|
});
|
|
1316
1355
|
return cb();
|
|
1317
1356
|
});
|
|
@@ -1416,10 +1455,12 @@ module.exports = exports = function(module, funcs){
|
|
|
1416
1455
|
//Additional parameters for static render
|
|
1417
1456
|
page: clientPage.page,
|
|
1418
1457
|
template: clientPage.template,
|
|
1458
|
+
|
|
1419
1459
|
sitemap: clientPage.sitemap,
|
|
1420
1460
|
getSitemapURL: function(sitemap_item){ return funcs.getSitemapUrl(sitemap_item, branchData); },
|
|
1421
1461
|
menu: null,
|
|
1422
1462
|
getMenuURL: function(menu_item){ return funcs.getMenuUrl(menu_item, branchData); },
|
|
1463
|
+
|
|
1423
1464
|
include: includePage,
|
|
1424
1465
|
}
|
|
1425
1466
|
if(renderOptions.menu_tag){
|
|
@@ -1465,9 +1506,14 @@ module.exports = exports = function(module, funcs){
|
|
|
1465
1506
|
include: includePage,
|
|
1466
1507
|
});
|
|
1467
1508
|
renderedContent = funcs.applyRenderTags(renderedContent, { page: ejsparams.page });
|
|
1509
|
+
renderedContent = funcs.applyResponsiveImg(renderedContent, branchData.site_config.media_thumbnails, branchData.media_items);
|
|
1468
1510
|
var replaceBranchURLsParams = {
|
|
1469
|
-
getMediaURL: function(media_key){
|
|
1511
|
+
getMediaURL: function(media_key, thumbnail_id){
|
|
1470
1512
|
if(!(media_key in branchData.media_keys)) throw new Error('Page '+page.page_path+' links to missing Media ID # '+media_key.toString());
|
|
1513
|
+
if(thumbnail_id){
|
|
1514
|
+
if(!(branchData.site_config.media_thumbnails && branchData.site_config.media_thumbnails[thumbnail_id])) throw new Error('Page '+page.page_path+', Media #'+media_key.toString()+' links to invalid Thumbnail ID: '+thumbnail_id);
|
|
1515
|
+
return funcs.appendThumbnail(branchData.media_keys[media_key], thumbnail_id, branchData.site_config.media_thumbnails && branchData.site_config.media_thumbnails[thumbnail_id]);
|
|
1516
|
+
}
|
|
1471
1517
|
return branchData.media_keys[media_key];
|
|
1472
1518
|
},
|
|
1473
1519
|
getPageURL: function(page_key){
|
|
@@ -1589,7 +1635,7 @@ module.exports = exports = function(module, funcs){
|
|
|
1589
1635
|
_.each(renderParams.menu.items, function(menu_item){ menu_item.selected = false; });
|
|
1590
1636
|
}
|
|
1591
1637
|
|
|
1592
|
-
var rslt = funcs.renderComponent(branchData.component_export_template_html[template_name][exportIndex] || '',
|
|
1638
|
+
var rslt = funcs.renderComponent(branchData.component_export_template_html[template_name][exportIndex] || '', branchData, renderOptions, renderParams);
|
|
1593
1639
|
if(exportItem.export_path){
|
|
1594
1640
|
branchData.fsOps.addFile(branchData.fsOps.getValidFilePath(exportItem.export_path), rslt);
|
|
1595
1641
|
}
|
|
@@ -1787,24 +1833,24 @@ module.exports = exports = function(module, funcs){
|
|
|
1787
1833
|
},
|
|
1788
1834
|
//Export thumbnails
|
|
1789
1835
|
function(generate_cb){
|
|
1790
|
-
async.eachOfSeries(branchData.site_config.media_thumbnails, function(thumbnail_config,
|
|
1836
|
+
async.eachOfSeries(branchData.site_config.media_thumbnails, function(thumbnail_config, thumbnail_id, thumbnail_cb){
|
|
1791
1837
|
if(!thumbnail_config || !thumbnail_config.export) return thumbnail_cb();
|
|
1792
|
-
if(!_.includes(['.jpg','.jpeg','.tif','.tiff','.png','.gif','.svg'], media.media_ext)) return
|
|
1838
|
+
if(!_.includes(['.jpg','.jpeg','.tif','.tiff','.png','.gif','.svg'], media.media_ext)) return thumbnail_cb();
|
|
1793
1839
|
|
|
1794
|
-
funcs.getMediaFile(media.media_file_id, media.media_filename, media.media_ext,
|
|
1795
|
-
if(err) return thumbnail_cb('Error getting thumbnail for '+media_fpath+':'+
|
|
1840
|
+
funcs.getMediaFile(media.media_file_id, media.media_filename, media.media_ext, thumbnail_id, thumbnail_config, function(err, thumbnail_srcpath, thumbnail_fname, stat){
|
|
1841
|
+
if(err) return thumbnail_cb('Error getting thumbnail for '+media_fpath+':'+thumbnail_id+' - '+err.toString());
|
|
1796
1842
|
|
|
1797
1843
|
fs.readFile(thumbnail_srcpath, null, function(err, thumbnail_content){
|
|
1798
1844
|
if(err) return thumbnail_cb(err);
|
|
1799
1845
|
|
|
1800
1846
|
var thumbnail_fpath = '';
|
|
1801
1847
|
try{
|
|
1802
|
-
thumbnail_fpath = funcs.getMediaRelativePath(media, publish_params,
|
|
1848
|
+
thumbnail_fpath = funcs.getMediaRelativePath(media, publish_params, thumbnail_id, thumbnail_config);
|
|
1803
1849
|
}
|
|
1804
1850
|
catch(ex){
|
|
1805
1851
|
return thumbnail_cb(ex);
|
|
1806
1852
|
}
|
|
1807
|
-
if(!thumbnail_fpath) return thumbnail_cb(new Error('Thumbnail deployment path could not be generated for: '+media.media_fpath+':'+
|
|
1853
|
+
if(!thumbnail_fpath) return thumbnail_cb(new Error('Thumbnail deployment path could not be generated for: '+media.media_fpath+':'+thumbnail_id));
|
|
1808
1854
|
|
|
1809
1855
|
branchData.site_files[thumbnail_fpath] = {
|
|
1810
1856
|
md5: crypto.createHash('md5').update(thumbnail_content).digest("hex")
|
|
@@ -888,6 +888,11 @@ module.exports = exports = function(module, funcs){
|
|
|
888
888
|
}
|
|
889
889
|
else {
|
|
890
890
|
wc.req(op.params[0], 'GET', {}, {}, undefined, function(err, res, templateContent){
|
|
891
|
+
if(err){
|
|
892
|
+
if((err.code=='DEPTH_ZERO_SELF_SIGNED_CERT')||(err.code=='SELF_SIGNED_CERT_IN_CHAIN')||(err.message=='self signed certificate')){
|
|
893
|
+
err.message = 'Self-signed certificate found for URL: '+op.params[0] + ' :: Select the "Ignore certificate errors when downloading remote templates" option in the Deployment Target configuration to allow self-signed certificates.';
|
|
894
|
+
}
|
|
895
|
+
}
|
|
891
896
|
op.params[1](err, res, templateContent, op.done);
|
|
892
897
|
}, { rejectUnauthorized: !publish_config.ignore_remote_template_certificate });
|
|
893
898
|
}
|
package/models/_funcs.media.js
CHANGED
|
@@ -29,22 +29,22 @@ module.exports = exports = function(module, funcs){
|
|
|
29
29
|
var exports = {};
|
|
30
30
|
var _t = module._t, _tN = module._tN;
|
|
31
31
|
|
|
32
|
-
exports.getMediaFilename = function(media_file_id, media_ext,
|
|
32
|
+
exports.getMediaFilename = function(media_file_id, media_ext, thumbnail_id, thumbnail_config){
|
|
33
33
|
var fname = media_file_id.toString();
|
|
34
|
-
if(
|
|
34
|
+
if(thumbnail_id) fname += '.' + thumbnail_id;
|
|
35
35
|
else if(thumbnail_config && thumbnail_config.resize){
|
|
36
36
|
fname += '.custom.'+(thumbnail_config.resize[0]||'').toString()+'x'+(thumbnail_config.resize[1]||'').toString();
|
|
37
37
|
}
|
|
38
38
|
else if(thumbnail_config) throw new Error('Unsupported media file name: '+JSON.stringify(thumbnail_config));
|
|
39
|
-
fname += media_ext;
|
|
39
|
+
fname += ((thumbnail_config && thumbnail_config.format) ? '.' + thumbnail_config.format : media_ext);
|
|
40
40
|
return path.join(path.join(module.jsh.Config.datadir,'media'),fname);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
exports.getMediaFile = function(media_file_id, media_filename, media_ext,
|
|
43
|
+
exports.getMediaFile = function(media_file_id, media_filename, media_ext, thumbnail_id, thumbnail_config, callback){
|
|
44
44
|
var jsh = module.jsh;
|
|
45
45
|
|
|
46
46
|
var srcpath = funcs.getMediaFilename(media_file_id, media_ext);
|
|
47
|
-
var fpath = funcs.getMediaFilename(media_file_id, media_ext,
|
|
47
|
+
var fpath = funcs.getMediaFilename(media_file_id, media_ext, thumbnail_id, thumbnail_config);
|
|
48
48
|
var fname = path.basename(media_filename);
|
|
49
49
|
|
|
50
50
|
if(thumbnail_config && thumbnail_config.format){
|
|
@@ -54,7 +54,7 @@ module.exports = exports = function(module, funcs){
|
|
|
54
54
|
|
|
55
55
|
var transformMedia = function(transform_callback){
|
|
56
56
|
if('resize' in thumbnail_config) jsh.Extensions.image.resize(srcpath, fpath, thumbnail_config.resize, thumbnail_config.format, transform_callback);
|
|
57
|
-
else if('crop' in thumbnail_config) jsh.Extensions.image.crop(srcpath, fpath, thumbnail_config.format, transform_callback);
|
|
57
|
+
else if('crop' in thumbnail_config) jsh.Extensions.image.crop(srcpath, fpath, thumbnail_config.crop, thumbnail_config.format, transform_callback);
|
|
58
58
|
else if('format' in thumbnail_config) jsh.Extensions.image.resample(srcpath, fpath, thumbnail_config.format, transform_callback);
|
|
59
59
|
else return transform_callback(new Error('Invalid thumbnail_config: '+JSON.stringify(thumbnail_config)));
|
|
60
60
|
}
|
|
@@ -68,16 +68,27 @@ module.exports = exports = function(module, funcs){
|
|
|
68
68
|
if(err) return callback(err);
|
|
69
69
|
fs.stat(fpath, function (err, stat) {
|
|
70
70
|
if(err) return callback(err);
|
|
71
|
-
return callback(null, fpath, stat);
|
|
71
|
+
return callback(null, fpath, fname, stat);
|
|
72
72
|
});
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
else return callback(err);
|
|
76
76
|
}
|
|
77
|
-
else return callback(null, fpath, stat);
|
|
77
|
+
else return callback(null, fpath, fname, stat);
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
exports.appendThumbnail = function(fpath, thumbnail_id, thumbnail_config){
|
|
82
|
+
if(!fpath) return fpath;
|
|
83
|
+
var fname = path.basename(fpath);
|
|
84
|
+
var fext = path.extname(fname);
|
|
85
|
+
fpath = fpath.substr(0, fpath.length - fext.length) + '.' + thumbnail_id + fext;
|
|
86
|
+
if(thumbnail_config && thumbnail_config.format){
|
|
87
|
+
if(fext.length > 1) fpath = fpath.substr(0, fpath.length - fext.length) + '.' + thumbnail_config.format;
|
|
88
|
+
}
|
|
89
|
+
return fpath;
|
|
90
|
+
}
|
|
91
|
+
|
|
81
92
|
exports.media = function (req, res, next) {
|
|
82
93
|
var verb = req.method.toLowerCase();
|
|
83
94
|
|
|
@@ -103,12 +114,12 @@ module.exports = exports = function(module, funcs){
|
|
|
103
114
|
if (verb == 'get'){
|
|
104
115
|
if(!req.params || !req.params.media_key) return next();
|
|
105
116
|
var media_key = req.params.media_key;
|
|
106
|
-
var
|
|
117
|
+
var thumbnail_id = req.params.thumbnail;
|
|
107
118
|
var thumbnail_config = null;
|
|
108
|
-
if(
|
|
119
|
+
if(thumbnail_id) thumbnail_config = siteConfig.media_thumbnails[thumbnail_id];
|
|
109
120
|
|
|
110
121
|
//Invalid Thumbnail
|
|
111
|
-
if(
|
|
122
|
+
if(thumbnail_id && !thumbnail_config) return next();
|
|
112
123
|
|
|
113
124
|
//Check if media exists
|
|
114
125
|
sql_ptypes = [dbtypes.BigInt];
|
|
@@ -167,11 +178,10 @@ module.exports = exports = function(module, funcs){
|
|
|
167
178
|
}
|
|
168
179
|
|
|
169
180
|
var serveoptions = { attachment: !!('download' in Q), mime_override: media.media_ext };
|
|
170
|
-
var fname = path.basename(media.media_filename);
|
|
171
181
|
|
|
172
182
|
if(thumbnail_config && thumbnail_config.format) serveoptions.mime_override = '.' + thumbnail_config.format;
|
|
173
183
|
|
|
174
|
-
funcs.getMediaFile(media.media_file_id, media.media_filename, media.media_ext,
|
|
184
|
+
funcs.getMediaFile(media.media_file_id, media.media_filename, media.media_ext, thumbnail_id, thumbnail_config, function(err, fpath, fname, stat){
|
|
175
185
|
if(err){
|
|
176
186
|
if(err.message == 'Media file not found') return Helper.GenError(req, res, -33, 'Media file not found.');
|
|
177
187
|
jsh.Log.error(err.toString() + '\n' + (err.stack?err.stack:(new Error()).stack));
|
package/models/_funcs.page.js
CHANGED
|
@@ -183,7 +183,7 @@ module.exports = exports = function(module, funcs){
|
|
|
183
183
|
|
|
184
184
|
exports.replaceBranchURLs = function(content, options){
|
|
185
185
|
options = _.extend({
|
|
186
|
-
getMediaURL: function(media_key, branchData, getLinkContent, urlparts){ return ''; },
|
|
186
|
+
getMediaURL: function(media_key, thumbnail_id, branchData, getLinkContent, thumbnail, urlparts){ return ''; },
|
|
187
187
|
getPageURL: function(page_key, branchData, getLinkContent, urlparts){ return ''; },
|
|
188
188
|
onError: function(err){ },
|
|
189
189
|
onComponentData: null, //function(content){ return content; },
|
|
@@ -221,13 +221,14 @@ module.exports = exports = function(module, funcs){
|
|
|
221
221
|
}
|
|
222
222
|
var urlparts = urlparser.parse(url, true);
|
|
223
223
|
if(!urlparts.path) return url;
|
|
224
|
-
var patharr = (urlparts.
|
|
224
|
+
var patharr = (urlparts.pathname||'').split('/');
|
|
225
225
|
|
|
226
226
|
if((urlparts.path.indexOf('/_funcs/media/')==0) && (patharr.length>=4)){
|
|
227
227
|
var media_key = patharr[3];
|
|
228
228
|
if(parseInt(media_key).toString()==media_key){
|
|
229
229
|
try{
|
|
230
|
-
var
|
|
230
|
+
var thumbnail_id = ((patharr.length >= 5) ? patharr[4] : '');
|
|
231
|
+
var media_url = options.getMediaURL(media_key, thumbnail_id, options.branchData, getLinkContent, urlparts);
|
|
231
232
|
}
|
|
232
233
|
catch(ex){
|
|
233
234
|
if(options.onError) options.onError(ex);
|
|
@@ -444,11 +445,11 @@ module.exports = exports = function(module, funcs){
|
|
|
444
445
|
|
|
445
446
|
function replaceURLs(content, options){
|
|
446
447
|
var rslt = funcs.replaceBranchURLs(content, _.extend({ replaceComponents: true }, options, {
|
|
447
|
-
getMediaURL: function(media_key, branchData, getLinkContent, urlparts){
|
|
448
|
+
getMediaURL: function(media_key, thumbnail_id, branchData, getLinkContent, urlparts){
|
|
448
449
|
if(!media_files){
|
|
449
|
-
return baseurl + urlparts.
|
|
450
|
+
return baseurl + urlparts.pathname.substr(1) + '#@JSHCMS';
|
|
450
451
|
}
|
|
451
|
-
return baseurl+'_funcs/media/'+media_key+'/?media_id='+media_files[media_key].media_id+'#@JSHCMS';
|
|
452
|
+
return baseurl+'_funcs/media/'+media_key+(thumbnail_id?'/'+thumbnail_id:'')+'/?media_id='+media_files[media_key].media_id+'#@JSHCMS';
|
|
452
453
|
},
|
|
453
454
|
getPageURL: function(page_key, branchData, getLinkContent, urlparts){
|
|
454
455
|
if(branch_id) return baseurl+'_funcs/page/'+page_key+'/?branch_id='+branch_id+'&view=1#@JSHCMS';
|
|
@@ -1241,6 +1242,7 @@ module.exports = exports = function(module, funcs){
|
|
|
1241
1242
|
if(!siteConfig) siteConfig = {};
|
|
1242
1243
|
var pageSiteConfig = {
|
|
1243
1244
|
defaultEditorConfig: siteConfig.defaultEditorConfig||{},
|
|
1245
|
+
media_thumbnails: {},
|
|
1244
1246
|
};
|
|
1245
1247
|
if(typeof pageSiteConfig.defaultEditorConfig.webSnippetsPath == 'undefined'){
|
|
1246
1248
|
if(cms.PreviewServer){
|
|
@@ -1249,6 +1251,10 @@ module.exports = exports = function(module, funcs){
|
|
|
1249
1251
|
pageSiteConfig.defaultEditorConfig.webSnippetsPath = webSnippetPath;
|
|
1250
1252
|
}
|
|
1251
1253
|
}
|
|
1254
|
+
_.each(siteConfig.media_thumbnails, function(thumbnail_config, thumbnail_id){
|
|
1255
|
+
if(!thumbnail_config || !thumbnail_config.export) return;
|
|
1256
|
+
pageSiteConfig.media_thumbnails[thumbnail_id] = true;
|
|
1257
|
+
});
|
|
1252
1258
|
res.end(JSON.stringify({ '_success': 1, siteConfig: pageSiteConfig }));
|
|
1253
1259
|
});
|
|
1254
1260
|
});
|
package/models/_funcs.search.js
CHANGED
|
@@ -120,11 +120,21 @@ module.exports = exports = function(module, funcs){
|
|
|
120
120
|
media_keys: {},
|
|
121
121
|
page_keys: {},
|
|
122
122
|
results: [],
|
|
123
|
+
site_config: {},
|
|
123
124
|
};
|
|
124
125
|
var sql_ptypes = [dbtypes.BigInt];
|
|
125
126
|
var sql_params = { 'branch_id': branch_id };
|
|
126
127
|
|
|
127
128
|
async.waterfall([
|
|
129
|
+
//Get site_config
|
|
130
|
+
function(search_cb){
|
|
131
|
+
funcs.getSiteConfig(req._DBContext, site_id, { continueOnConfigError: true }, function(err, siteConfig){
|
|
132
|
+
if(err) return search_cb(err);
|
|
133
|
+
searchData.site_config = siteConfig || {};
|
|
134
|
+
return search_cb();
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
//Search pages
|
|
128
138
|
function(search_cb){
|
|
129
139
|
async.eachOfSeries(cms.BranchItems, function(branch_item, branch_item_type, search_item_cb){
|
|
130
140
|
if(!branch_item.search) return search_item_cb();
|
|
@@ -289,8 +299,9 @@ module.exports = exports = function(module, funcs){
|
|
|
289
299
|
return content;
|
|
290
300
|
}
|
|
291
301
|
var rslt = funcs.replaceBranchURLs(content, _.extend({ replaceComponents: true }, {
|
|
292
|
-
getMediaURL: function(media_key){
|
|
302
|
+
getMediaURL: function(media_key, thumbnail_id){
|
|
293
303
|
if(!(media_key in searchData.media_keys)) return '';
|
|
304
|
+
if(thumbnail_id) return funcs.appendThumbnail(searchData.media_keys[media_key], thumbnail_id, searchData.site_config.media_thumbnails && searchData.site_config.media_thumbnails[thumbnail_id]);
|
|
294
305
|
return searchData.media_keys[media_key];
|
|
295
306
|
},
|
|
296
307
|
getPageURL: function(page_key){
|
|
@@ -25,6 +25,7 @@ var path = require('path');
|
|
|
25
25
|
var fs = require('fs');
|
|
26
26
|
var parse5 = require('parse5');
|
|
27
27
|
var crypto = require('crypto');
|
|
28
|
+
var urlparser = require('url');
|
|
28
29
|
|
|
29
30
|
module.exports = exports = function(module, funcs){
|
|
30
31
|
var exports = {};
|
|
@@ -1683,6 +1684,110 @@ module.exports = exports = function(module, funcs){
|
|
|
1683
1684
|
return htdoc.content;
|
|
1684
1685
|
}
|
|
1685
1686
|
|
|
1687
|
+
exports.applyResponsiveImg = function(content, thumbnails, media_items){
|
|
1688
|
+
if(!content) return content;
|
|
1689
|
+
media_items = media_items || {};
|
|
1690
|
+
|
|
1691
|
+
var responsiveThumbnails = {};
|
|
1692
|
+
if(thumbnails) for(var key in thumbnails){
|
|
1693
|
+
if(thumbnails[key].responsive) responsiveThumbnails[key] = thumbnails[key];
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
if(_.isEmpty(responsiveThumbnails)) return content;
|
|
1697
|
+
|
|
1698
|
+
//If no img tags, return
|
|
1699
|
+
if(content.toLowerCase().indexOf('img') < 0) return content;
|
|
1700
|
+
|
|
1701
|
+
var htdoc = new funcs.HTMLDoc(content);
|
|
1702
|
+
htdoc.applyNodes([
|
|
1703
|
+
{ //img tags
|
|
1704
|
+
pred: function(node){ return htdoc.isTag(node, 'img'); },
|
|
1705
|
+
exec: function(node){
|
|
1706
|
+
var src = (htdoc.getAttr(node, 'src')||'').toString();
|
|
1707
|
+
if(!src) return;
|
|
1708
|
+
if(htdoc.hasAttr(node, 'srcset')) return;
|
|
1709
|
+
|
|
1710
|
+
//Check for #@JSHCMS
|
|
1711
|
+
var urlparts = null;
|
|
1712
|
+
try{
|
|
1713
|
+
urlparts = urlparser.parse(src, true);
|
|
1714
|
+
}
|
|
1715
|
+
catch(ex){
|
|
1716
|
+
}
|
|
1717
|
+
if(!urlparts) return;
|
|
1718
|
+
|
|
1719
|
+
if(!Helper.beginsWith(urlparts.hash || '', '#@JSHCMS')) return;
|
|
1720
|
+
if((urlparts.pathname||'').indexOf('/_funcs/media/')!=0) return;
|
|
1721
|
+
|
|
1722
|
+
var patharr = (urlparts.pathname||'').split('/');
|
|
1723
|
+
if(patharr.length < 4) return;
|
|
1724
|
+
var media_key = patharr[3];
|
|
1725
|
+
var media_thumbnail = patharr[4];
|
|
1726
|
+
|
|
1727
|
+
//Check if media_key is valid
|
|
1728
|
+
var media_item = media_items[media_key];
|
|
1729
|
+
var media_width = 0;
|
|
1730
|
+
var media_height = 0;
|
|
1731
|
+
if(media_item){
|
|
1732
|
+
if(media_item.media_width) media_width = media_item.media_width;
|
|
1733
|
+
if(media_item.media_height) media_height = media_item.media_height;
|
|
1734
|
+
}
|
|
1735
|
+
if(media_thumbnail && (media_thumbnail in thumbnails)){
|
|
1736
|
+
var tgtThumbnail = thumbnails[media_thumbnail];
|
|
1737
|
+
if(tgtThumbnail.resize && tgtThumbnail.resize.length){
|
|
1738
|
+
media_width = tgtThumbnail.resize[0];
|
|
1739
|
+
media_height = tgtThumbnail.resize[1];
|
|
1740
|
+
}
|
|
1741
|
+
else if(tgtThumbnail.crop && tgtThumbnail.crop.length){
|
|
1742
|
+
media_width = tgtThumbnail.crop[0];
|
|
1743
|
+
media_height = tgtThumbnail.crop[1];
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
var srcsets = [];
|
|
1748
|
+
var max_width = media_width;
|
|
1749
|
+
for(var thumbnail_id in responsiveThumbnails){
|
|
1750
|
+
var thumbnail = responsiveThumbnails[thumbnail_id];
|
|
1751
|
+
var srcsetCondition = '';
|
|
1752
|
+
if(_.isString(thumbnail.responsive)) srcsetCondition = thumbnail.responsive;
|
|
1753
|
+
else {
|
|
1754
|
+
var thumbnail_width = 0;
|
|
1755
|
+
if(media_item && media_item.media_width) thumbnail_width = media_item.media_width;
|
|
1756
|
+
if(thumbnail.resize && thumbnail.resize.length) thumbnail_width = thumbnail.resize[0];
|
|
1757
|
+
else if(thumbnail.crop && thumbnail.crop.length) thumbnail_width = thumbnail.crop[0];
|
|
1758
|
+
|
|
1759
|
+
if(thumbnail_width && (!media_width || (thumbnail_width < media_width))){
|
|
1760
|
+
srcsetCondition = thumbnail_width + 'w';
|
|
1761
|
+
if(thumbnail_width >= max_width) max_width = thumbnail_width + 1;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
if(srcsetCondition){
|
|
1766
|
+
//Generate srcset
|
|
1767
|
+
var srcsetUrl = urlparts.protocol+'//'+urlparts.host+'/_funcs/media/'+media_key+'/'+thumbnail_id+'/#@JSHCMS'+urlparts.hash.substr(('#@JSHCMS').length);
|
|
1768
|
+
srcsets.push(srcsetUrl+' '+srcsetCondition);
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
//Update img tag
|
|
1773
|
+
if(srcsets.length){
|
|
1774
|
+
srcsets.push(src + ' ' + max_width + 'w');
|
|
1775
|
+
htdoc.appendAttr(node, 'srcset', srcsets.join(', '), 'srcset');
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
if(media_width && media_height && htdoc.hasAttr(node, 'cms-image-dimensions')){
|
|
1779
|
+
if(!htdoc.hasAttr(node, 'width') && !htdoc.hasAttr(node, 'height')){
|
|
1780
|
+
htdoc.appendAttr(node, 'width', media_width.toString());
|
|
1781
|
+
htdoc.appendAttr(node, 'height', media_height.toString());
|
|
1782
|
+
htdoc.removeAttr(node, 'cms-image-dimensions');
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
},
|
|
1787
|
+
]);
|
|
1788
|
+
return htdoc.content;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1686
1791
|
exports.generateEditorTemplate = function(content, options){
|
|
1687
1792
|
options = _.extend({ cmsBaseUrl: '/', template_variables: {} }, options);
|
|
1688
1793
|
|
|
@@ -130,15 +130,6 @@ module.exports = exports = function(module, funcs){
|
|
|
130
130
|
|
|
131
131
|
async.waterfall([
|
|
132
132
|
|
|
133
|
-
//Get site config
|
|
134
|
-
function(cb){
|
|
135
|
-
funcs.getSiteConfig('deployment', branchData.site_id, { }, function(err, siteConfig){
|
|
136
|
-
if(err) return cb(err);
|
|
137
|
-
branchData.site_config = siteConfig || {};
|
|
138
|
-
return cb();
|
|
139
|
-
});
|
|
140
|
-
},
|
|
141
|
-
|
|
142
133
|
//Get template_variables for branch
|
|
143
134
|
function(cb){
|
|
144
135
|
var sql = "select site_editor deployment_target_id, v_my_site.deployment_target_template_variables, v_my_branch_desc.site_id, deployment_target_publish_config, deployment_target_publish_path from {schema}.v_my_branch_desc left outer join {schema}.v_my_site on v_my_site.site_id = v_my_branch_desc.site_id left outer join {schema}.deployment_target on deployment_target.deployment_target_id = v_my_site.deployment_target_id where v_my_branch_desc.branch_id=@branch_id";
|
|
@@ -167,16 +158,22 @@ module.exports = exports = function(module, funcs){
|
|
|
167
158
|
return deploy_cb('Error parsing deployment_target_publish_config: '+ex.toString());
|
|
168
159
|
}
|
|
169
160
|
|
|
170
|
-
|
|
161
|
+
//Get site config
|
|
162
|
+
funcs.getSiteConfig('deployment', branchData.site_id, { }, function(err, siteConfig){
|
|
171
163
|
if(err) return cb(err);
|
|
172
|
-
|
|
173
|
-
|
|
164
|
+
branchData.site_config = siteConfig || {};
|
|
165
|
+
|
|
166
|
+
funcs.parseTemplateVariables('publish', 'deployment', branchData.site_id, branchData.site_config, template_variables, deployment_target_publish_config, function(err, parsed_template_variables){
|
|
167
|
+
if(err) return cb(err);
|
|
168
|
+
template_variables = parsed_template_variables;
|
|
169
|
+
branchData.template_variables = template_variables;
|
|
174
170
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
171
|
+
//Deployment Target Publish Params
|
|
172
|
+
var publish_params = _.extend(JSON.parse(JSON.stringify(template_variables)), deployment_target_publish_config);
|
|
173
|
+
branchData.publish_params = publish_params;
|
|
178
174
|
|
|
179
|
-
|
|
175
|
+
return cb();
|
|
176
|
+
});
|
|
180
177
|
});
|
|
181
178
|
});
|
|
182
179
|
},
|
|
@@ -322,8 +319,11 @@ module.exports = exports = function(module, funcs){
|
|
|
322
319
|
if(page.compiled.content) for(var key in page.compiled.content) allContent[key + ' content'] = page.compiled.content[key];
|
|
323
320
|
for(var key in allContent){
|
|
324
321
|
funcs.replaceBranchURLs(allContent[key], {
|
|
325
|
-
getMediaURL: function(media_key, branchData, getLinkContent){
|
|
322
|
+
getMediaURL: function(media_key, thumbnail_id, branchData, getLinkContent){
|
|
326
323
|
if(!(media_key in branchData.media_keys)) throw new Error('<' + key + '>: Link to missing Media ID #'+media_key.toString()+': ...'+getLinkContent()+'...');
|
|
324
|
+
if(thumbnail_id){
|
|
325
|
+
if(!(branchData.site_config.media_thumbnails && branchData.site_config.media_thumbnails[thumbnail_id])) throw new Error('<' + key + '>: Media #'+media_key.toString()+' links to invalid Thumbnail ID: '+thumbnail_id+' ...'+getLinkContent()+'...');
|
|
326
|
+
}
|
|
327
327
|
return '';
|
|
328
328
|
},
|
|
329
329
|
getPageURL: function(page_key, branchData, getLinkContent){
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsharmony-cms",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "jsHarmony CMS",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"diff2html": "3.4.1",
|
|
31
31
|
"ejs": "2.7.4",
|
|
32
32
|
"js-beautify": "^1.11.0",
|
|
33
|
-
"jsharmony": "^1.
|
|
34
|
-
"jsharmony-factory": "^1.
|
|
33
|
+
"jsharmony": "^1.4.0",
|
|
34
|
+
"jsharmony-factory": "^1.2.0",
|
|
35
35
|
"lodash": "^4.17.19",
|
|
36
36
|
"node-forge": "^0.10.0",
|
|
37
37
|
"parse5": "^6.0.1",
|
|
@@ -579,7 +579,9 @@ DataModelTemplate_GridPreview.prototype.buildTemplate = function(componentTempla
|
|
|
579
579
|
model.oncommit = '_this.onCommit(xmodel, rowid, callback);';
|
|
580
580
|
model.ejs = '';
|
|
581
581
|
model.sort = { [this._sequenceFieldName]: 'asc' };
|
|
582
|
-
model.oninit =
|
|
582
|
+
model.oninit = [
|
|
583
|
+
"jsh.$root('.xform'+xmodel.class).before('<div class=\"dataGridEditor_instructions\"><span style=\"font-size:1.3em;position:relative;top:1px;margin-right:2px;margin-left:4px;\">🛈</span> Add, edit, and re-order items using the icons <span class=\"dataGridEditor_instructions_doubleClick\">:: Double-click to edit</span></div>');",
|
|
584
|
+
].join(' ');
|
|
583
585
|
model.rowclass = "<%=xejs.iif(rowid==0,'first')%>";
|
|
584
586
|
model.tableclass = ((model.tableclass||'')+' '+(componentConfig&&componentConfig.options&&componentConfig.options.component_preview_size=='collapse'?'jsharmony_cms_component_preview_collapse':'jsharmony_cms_component_preview_expand')).trim();
|
|
585
587
|
this._jsh.XPage.ParseModelDefinition(model, null, null, { ignoreErrors: true });
|
|
@@ -3786,6 +3788,8 @@ TemplateRenderer.render = function(config, type, jsh, cms, componentConfig, addi
|
|
|
3786
3788
|
isInEditor: true,
|
|
3787
3789
|
isInPageEditor: true,
|
|
3788
3790
|
isInComponentEditor: ((type=='gridRowDataPreview') || (type=='gridItemPreview')),
|
|
3791
|
+
componentRenderClass: 'jsharmony_cms_componentRender_'+jsh.XExt.escapeCSSClass((componentConfig&&componentConfig.id)||'')+'_'+cms.componentManager.getUniqueId().toString(),
|
|
3792
|
+
getMediaThumbnails: function(url){ return cms.componentManager.getMediaThumbnails(url); },
|
|
3789
3793
|
renderPlaceholder: renderPlaceholder,
|
|
3790
3794
|
}, additionalRenderParams));
|
|
3791
3795
|
|
|
@@ -4329,6 +4333,8 @@ exports = module.exports = function(jsh, cms){
|
|
|
4329
4333
|
this.containerlessComponents = {};
|
|
4330
4334
|
this.cntContainerlessComponents = 0;
|
|
4331
4335
|
|
|
4336
|
+
var maxUniqueId = 0;
|
|
4337
|
+
|
|
4332
4338
|
this.load = function(onError){
|
|
4333
4339
|
_this.loadSystemComponentTemplates(onError);
|
|
4334
4340
|
}
|
|
@@ -4670,6 +4676,8 @@ exports = module.exports = function(jsh, cms){
|
|
|
4670
4676
|
isInEditor: true,
|
|
4671
4677
|
isInPageEditor: false,
|
|
4672
4678
|
isInComponentEditor: false,
|
|
4679
|
+
componentRenderClass: 'jsharmony_cms_componentRender_'+XExt.escapeCSSClass((component&&component.id)||'')+'_'+cms.componentManager.getUniqueId().toString(),
|
|
4680
|
+
getMediaThumbnails: function(url){ return cms.componentManager.getMediaThumbnails(url); },
|
|
4673
4681
|
items: data.items,
|
|
4674
4682
|
item: data.item,
|
|
4675
4683
|
component: properties,
|
|
@@ -4696,6 +4704,26 @@ exports = module.exports = function(jsh, cms){
|
|
|
4696
4704
|
}
|
|
4697
4705
|
return rslt;
|
|
4698
4706
|
}
|
|
4707
|
+
|
|
4708
|
+
this.getUniqueId = function(){ return ++maxUniqueId; }
|
|
4709
|
+
|
|
4710
|
+
this.getMediaThumbnails = function(url){
|
|
4711
|
+
if(!cms.site_config || !cms.site_config.media_thumbnails) return {};
|
|
4712
|
+
if(!url || (url.indexOf('#@JSHCMS') < 0)) return {};
|
|
4713
|
+
|
|
4714
|
+
var urlparts = document.createElement('a');
|
|
4715
|
+
urlparts.href = url;
|
|
4716
|
+
var patharr = (urlparts.pathname||'').split('/');
|
|
4717
|
+
var rslt = {};
|
|
4718
|
+
if(((urlparts.pathname||'').indexOf('/_funcs/media/')==0) && (patharr.length>=4)){
|
|
4719
|
+
for(var thumbnail_id in cms.site_config.media_thumbnails){
|
|
4720
|
+
if((patharr.length >= 5) && patharr[4]) patharr[4] = thumbnail_id;
|
|
4721
|
+
else patharr.splice(4,0,thumbnail_id);
|
|
4722
|
+
rslt[thumbnail_id] = urlparts.protocol + '//' + urlparts.host + patharr.join('/') + (urlparts.search||'') + (urlparts.hash||'');
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
return rslt;
|
|
4726
|
+
}
|
|
4699
4727
|
}
|
|
4700
4728
|
},{"./jsHarmonyCMS.Component":21}],23:[function(require,module,exports){
|
|
4701
4729
|
/*
|
|
@@ -6146,6 +6174,9 @@ exports = module.exports = function(jsh, cms, toolbarContainer){
|
|
|
6146
6174
|
],
|
|
6147
6175
|
contextmenu: 'jsharmonycmscomponentcontextmenu link linkchecker image imagetools table spellchecker configurepermanentpen',
|
|
6148
6176
|
toolbar: 'formatselect | backcolor forecolor | bold italic underline | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image charmapmaterialicons table fullscreen | jsHarmonyCmsWebSnippet | jsHarmonyCmsComponent | jsHarmonyCmsView | jsHarmonyCmsEndEdit',
|
|
6177
|
+
mobile: {
|
|
6178
|
+
toolbar_mode: 'floating',
|
|
6179
|
+
},
|
|
6149
6180
|
removed_menuitems: 'newdocument',
|
|
6150
6181
|
image_advtab: true,
|
|
6151
6182
|
menu: {
|
|
@@ -667,4 +667,28 @@ span[data-component] {
|
|
|
667
667
|
right:6px;
|
|
668
668
|
cursor:pointer;
|
|
669
669
|
font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
@media screen and (max-width: 500px) {
|
|
673
|
+
.jsharmony_cms .xactions.secondaryform {
|
|
674
|
+
padding-top:20px;
|
|
675
|
+
}
|
|
676
|
+
.jsharmony_cms .xactions.secondarygrid {
|
|
677
|
+
padding-top:14px;
|
|
678
|
+
}
|
|
679
|
+
.jsharmony_cms_dialog .jsharmony_cms_component_dialog > .xbodyhead {
|
|
680
|
+
position:relative;
|
|
681
|
+
}
|
|
682
|
+
.jsharmony_cms_component_dataGridEditor .dataGridEditor_instructions {
|
|
683
|
+
border-right: 2px solid #eee;
|
|
684
|
+
}
|
|
685
|
+
.dataGridEditor_instructions_doubleClick {
|
|
686
|
+
display:none;
|
|
687
|
+
}
|
|
688
|
+
.xdialogbox.jsharmony_cms_component_dialog {
|
|
689
|
+
min-width:auto !important;
|
|
690
|
+
}
|
|
691
|
+
.jsharmony_cms_component_dataGridEditor [data-component-template="gridRow"] .component_toolbar {
|
|
692
|
+
text-align:left;
|
|
693
|
+
}
|
|
670
694
|
}
|
package/views/jsh_cms_editor.ejs
CHANGED
|
@@ -281,6 +281,7 @@ cms-content-editor
|
|
|
281
281
|
cms-content-editor-type
|
|
282
282
|
cms-component-editor-remove-class
|
|
283
283
|
cms-component-editor-add-class
|
|
284
|
+
cms-image-dimensions
|
|
284
285
|
|
|
285
286
|
===================
|
|
286
287
|
EJS Container Slurp
|
|
@@ -303,6 +304,7 @@ getEJSOutput(f)
|
|
|
303
304
|
getSitemapURL(sitemap_item)
|
|
304
305
|
getMenuURL(menu_item)
|
|
305
306
|
renderPlaceholder({ errors: '' })
|
|
307
|
+
getMediaThumbnails(url)
|
|
306
308
|
|
|
307
309
|
* Only available for Export Components
|
|
308
310
|
addFile(filePath, fileContent)
|
|
@@ -318,6 +320,7 @@ baseUrl
|
|
|
318
320
|
isInEditor
|
|
319
321
|
isInPageEditor
|
|
320
322
|
isInComponentEditor
|
|
323
|
+
componentRenderClass
|
|
321
324
|
sitemap
|
|
322
325
|
menu (from cms-menu-tag)
|
|
323
326
|
data { item: <object>, items: Array<object> }
|