6 changed files with 308 additions and 3 deletions
@ -0,0 +1,34 @@ |
|||||
|
{ |
||||
|
"name": "<%= blockGroupName %>/<%= blockFilename %>", |
||||
|
"version": "1.0.0", |
||||
|
"title": "<%= title %>", |
||||
|
"categories": [], |
||||
|
"icon": "shortcode", |
||||
|
"preview_image": "", |
||||
|
"field_groups": [ |
||||
|
{ |
||||
|
"name": "content", |
||||
|
"label": "Content", |
||||
|
"fields": { |
||||
|
"title": { |
||||
|
"type": "text", |
||||
|
"label": "Title" |
||||
|
}, |
||||
|
"content": { |
||||
|
"type": "wysiwyg", |
||||
|
"label": "Content" |
||||
|
}, |
||||
|
"cta": { |
||||
|
"type": "link", |
||||
|
"label": "CTA" |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"name": "styling", |
||||
|
"label": "Styling", |
||||
|
"fields": { |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
// TODO: Same function is located in "/generators/block/index.cjs" file. Find a way to remove cjs files.
|
||||
|
export function capitalize(str) { |
||||
|
if (typeof str !== 'string') { |
||||
|
return ''; |
||||
|
} |
||||
|
|
||||
|
return str |
||||
|
.toLowerCase() |
||||
|
.split(/[ -_]/g) |
||||
|
.filter((word) => !!word) |
||||
|
.map((word) => { |
||||
|
return word.charAt(0).toUpperCase() + word.slice(1); |
||||
|
}) |
||||
|
.join(' '); |
||||
|
} |
||||
@ -0,0 +1,226 @@ |
|||||
|
import {readFile, writeFile, mkdir, copyFile} from "fs/promises"; |
||||
|
import {capitalize} from "../../helpers.js"; |
||||
|
|
||||
|
export async function buildHubspot(blockName) { |
||||
|
const distPath = `./exports/hubspot/${blockName}.module`; |
||||
|
await mkdir(distPath, {recursive: true}) |
||||
|
await copyFile(`./src/${blockName}.template.hbs`, `${distPath}/module.html`) |
||||
|
|
||||
|
const metaData = { |
||||
|
global: false, |
||||
|
host_template_types: ["EMAIL"], |
||||
|
label: capitalize(blockName), |
||||
|
is_available_for_new_content: true |
||||
|
} |
||||
|
|
||||
|
await writeFile(`${distPath}/meta.json`, JSON.stringify(metaData, null, 4)); |
||||
|
|
||||
|
const blockJSON = await readFile(`./block.json`, "utf8"); |
||||
|
const block = JSON.parse(blockJSON); |
||||
|
|
||||
|
const fields = getBlockFields(block, 'content'); |
||||
|
|
||||
|
// Styling TAB.
|
||||
|
const stylingFields = getBlockFields(block, 'styling'); |
||||
|
|
||||
|
if (stylingFields.length) { |
||||
|
const stylingFieldsByName = {}; |
||||
|
stylingFields.forEach(field => stylingFieldsByName[field.name] = field); |
||||
|
|
||||
|
const stylingGroup = convertToHubspotField({ |
||||
|
type: 'group', |
||||
|
name: 'style', |
||||
|
label: "Style", |
||||
|
sub_fields: stylingFieldsByName, |
||||
|
}); |
||||
|
stylingGroup.tab = "STYLE"; |
||||
|
|
||||
|
fields.push(stylingGroup); |
||||
|
} |
||||
|
|
||||
|
// Export JSON file.
|
||||
|
await writeFile(`${distPath}/fields.json`, JSON.stringify(fields, null, 4)); |
||||
|
} |
||||
|
|
||||
|
function getBlockFields(block = {}, type = 'content') { |
||||
|
const fields_group = block['field_groups'].find((group) => group.name === type); |
||||
|
const fields = []; |
||||
|
|
||||
|
if (!fields_group) { |
||||
|
return fields; |
||||
|
} |
||||
|
|
||||
|
Object.keys(fields_group['fields']).forEach((key) => { |
||||
|
const field = fields_group['fields'][key]; |
||||
|
field['name'] = key; |
||||
|
|
||||
|
fields.push(field); |
||||
|
}); |
||||
|
|
||||
|
return fields.map((field) => { |
||||
|
return convertToHubspotField(field); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function convertToHubspotField(field = {}) { |
||||
|
const data = { |
||||
|
id: field.name, |
||||
|
name: field.name, |
||||
|
label: field.label, |
||||
|
display_width: null, |
||||
|
validation_regex: "", |
||||
|
required: false, |
||||
|
locked: false, |
||||
|
default: field.default |
||||
|
}; |
||||
|
|
||||
|
let sub_fields = []; |
||||
|
|
||||
|
switch (field.type) { |
||||
|
case 'text': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "text", |
||||
|
allow_new_line: true, |
||||
|
show_emoji_picker: false, |
||||
|
}); |
||||
|
case 'wysiwyg': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "richtext" |
||||
|
}); |
||||
|
case 'number': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "number", |
||||
|
display: "text", |
||||
|
step: 1, |
||||
|
}); |
||||
|
case 'range': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "number", |
||||
|
display: "slider", |
||||
|
min: 0, |
||||
|
max: 100, |
||||
|
step: 3, |
||||
|
}); |
||||
|
case 'boolean': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "boolean", |
||||
|
display: "toggle", |
||||
|
}); |
||||
|
case 'checkbox': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "boolean", |
||||
|
display: "checkbox", |
||||
|
}); |
||||
|
case 'select': |
||||
|
const choices = []; |
||||
|
Object.keys(data.choices).forEach(value => choices.push([value, data.choices[value]])); |
||||
|
|
||||
|
return Object.assign({}, data, { |
||||
|
type: "select", |
||||
|
choices: [choices] |
||||
|
}); |
||||
|
case 'link': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "url", |
||||
|
supported_types: [ |
||||
|
"EXTERNAL" |
||||
|
], |
||||
|
default: { |
||||
|
content_id: null, |
||||
|
href: "https://www.twitter.com/...", |
||||
|
type: "EXTERNAL" |
||||
|
} |
||||
|
}); |
||||
|
case 'image': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "image", |
||||
|
responsive: true, |
||||
|
resizable: false, |
||||
|
show_loading: false, |
||||
|
default: { |
||||
|
src: "", |
||||
|
alt: null, |
||||
|
loading: "lazy" |
||||
|
} |
||||
|
}); |
||||
|
case 'file': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "file", |
||||
|
picker: "file", |
||||
|
}); |
||||
|
case 'stringList': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "text", |
||||
|
occurrence: { |
||||
|
min: null, |
||||
|
max: null, |
||||
|
sorting_label_field: null, |
||||
|
default: null, |
||||
|
}, |
||||
|
allow_new_line: false, |
||||
|
show_emoji_picker: false, |
||||
|
}); |
||||
|
case 'gallery': |
||||
|
return Object.assign({}, data, { |
||||
|
type: "image", |
||||
|
occurrence: { |
||||
|
min: null, |
||||
|
max: null, |
||||
|
sorting_label_field: null, |
||||
|
default: null |
||||
|
}, |
||||
|
responsive: true, |
||||
|
resizable: false, |
||||
|
show_loading: false, |
||||
|
default: { |
||||
|
src: "", |
||||
|
alt: null, |
||||
|
loading: "lazy" |
||||
|
} |
||||
|
}); |
||||
|
case 'group': |
||||
|
field.sub_fields = field.sub_fields || {}; |
||||
|
sub_fields = Object.keys(field.sub_fields).map(name => { |
||||
|
const sub_field = Object.assign({}, field.sub_fields[name], {name: `${field.name}_${name}`}); |
||||
|
return convertToHubspotField(sub_field); |
||||
|
}) |
||||
|
|
||||
|
return Object.assign({}, data, { |
||||
|
type: "group", |
||||
|
children: sub_fields, |
||||
|
tab: "CONTENT", |
||||
|
expanded: false, |
||||
|
default: {} |
||||
|
}); |
||||
|
case 'repeater': |
||||
|
field.sub_fields = field.sub_fields || {}; |
||||
|
sub_fields = Object.keys(field.sub_fields).map(name => { |
||||
|
const sub_field = Object.assign({}, field.sub_fields[name], {name: `${field.name}_${name}`}); |
||||
|
return convertToHubspotField(sub_field); |
||||
|
}) |
||||
|
|
||||
|
return Object.assign({}, data, { |
||||
|
type: "group", |
||||
|
children: sub_fields, |
||||
|
occurrence: { |
||||
|
min: null, |
||||
|
max: null, |
||||
|
sorting_label_field: null, |
||||
|
default: null, |
||||
|
}, |
||||
|
tab: "CONTENT", |
||||
|
expanded: false, |
||||
|
default: {} |
||||
|
}); |
||||
|
|
||||
|
// case 'YOUR_FIELD':
|
||||
|
// return Object.assign({}, data, {});
|
||||
|
default: |
||||
|
// type === 'string'
|
||||
|
return Object.assign({}, data, { |
||||
|
type: "text", |
||||
|
allow_new_line: false, |
||||
|
show_emoji_picker: true, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue