Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 92e4f1ea2d | |||
| 0062bb4506 | |||
| 5dd326be0f | |||
| bcad45d1e8 | |||
| 3daa725309 | |||
| 438619c4d9 | |||
| 1b2795fa40 | |||
| 31786581bd | |||
| e25f1aa4f1 | |||
| f3cd0e5876 | |||
| d6b0ff866b | |||
| 4a7ddf7d29 | |||
| 03a8833f46 | |||
| bf8f0e857d | |||
| b76f83d4fa | |||
| 977ec0003c | |||
| 0e91c42e89 | |||
| 0a4fd3608f | |||
| 11152dda87 | |||
| 246c9ddd35 | |||
| 164ef7433a | |||
| a6decb9cfb | |||
| 9c85a89a8f | |||
| 58ed3de9dc | |||
| 3de4a4abb6 | |||
| 256450226b | |||
| 51db3da072 | |||
| 05c5697bc2 | |||
| 01e4160040 | |||
| 81f5166043 | |||
| a1929fe33c | |||
| 840c002834 | |||
| f4474fb7e4 | |||
| 8ca6cb0365 | |||
| e2553358be | |||
| 34dbff5701 | |||
| c408f2f5b3 |
@@ -9,17 +9,8 @@ const {isDev, developmentBlockName} = getConfigs();
|
|||||||
const blockName = !isDev && config.has('blockName') ? config.get('blockName') : developmentBlockName;
|
const blockName = !isDev && config.has('blockName') ? config.get('blockName') : developmentBlockName;
|
||||||
|
|
||||||
export const PLATFORM_OPTIONS = [{
|
export const PLATFORM_OPTIONS = [{
|
||||||
name: 'wordpress-acf-block',
|
|
||||||
title: 'WordPress AFC Block'
|
|
||||||
}, {
|
|
||||||
name: 'wordpress',
|
name: 'wordpress',
|
||||||
title: 'WordPress'
|
title: 'WordPress'
|
||||||
}, {
|
|
||||||
name: 'wordpress-component-manager',
|
|
||||||
title: 'WordPress (Component Manager)'
|
|
||||||
}, {
|
|
||||||
name: 'wordpress-elementor',
|
|
||||||
title: 'WordPress Elementor'
|
|
||||||
}, {
|
}, {
|
||||||
name: 'hubspot',
|
name: 'hubspot',
|
||||||
title: 'Hubspot'
|
title: 'Hubspot'
|
||||||
|
|||||||
+201
-42
@@ -9,6 +9,11 @@ import archiver from "archiver";
|
|||||||
import {buildWordPress} from "./platforms/wordpress/wordpress-adapter.js";
|
import {buildWordPress} from "./platforms/wordpress/wordpress-adapter.js";
|
||||||
import {buildHubspotEmail} from "./platforms/hubspot/hubspot-email-adapter.js";
|
import {buildHubspotEmail} from "./platforms/hubspot/hubspot-email-adapter.js";
|
||||||
import {buildHubspotPage} from "./platforms/hubspot/hubspot-page-adapter.js";
|
import {buildHubspotPage} from "./platforms/hubspot/hubspot-page-adapter.js";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
import {constants} from "fs";
|
||||||
|
import fetch from "node-fetch";
|
||||||
|
import mime from "mime-types";
|
||||||
|
import {exec} from "child_process";
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
@@ -26,6 +31,7 @@ export async function readJSONFile(jsonFile) {
|
|||||||
let data = {};
|
let data = {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await fs.access(jsonFile, constants.F_OK | constants.R_OK);
|
||||||
data = await fsExtra.readJson(jsonFile);
|
data = await fsExtra.readJson(jsonFile);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
@@ -44,16 +50,19 @@ function getErrorHtml(message = '', errorMessage = '') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getBlockData(jsonFileName = 'default', {projectPath} = {jsonFileName: 'default'}) {
|
export async function getBlockData(jsonFileName = 'default', {projectPath} = {jsonFileName: 'default'}) {
|
||||||
let data = await readJSONFile(path.join(projectPath, 'data', `${jsonFileName}.json`));
|
const filePath = path.join(projectPath, 'data', `${jsonFileName}.json`);
|
||||||
|
const data = await readJSONFile(filePath);
|
||||||
|
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
return data;
|
console.log(filePath, data.errorMessage.replace(/<[^>]*>?/gm, ''));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBlockConfigs(args = {modulesPath: '', dataFiles: []}) {
|
export function getBlockConfigs(args = {modulesPath: '', dataFiles: []}) {
|
||||||
return Object.assign(JSON.parse(JSON.stringify(config)), // The entire config object.
|
const updatedConfig = Object.assign(JSON.parse(JSON.stringify(config)), // The entire config object.
|
||||||
{
|
{
|
||||||
projectDir: args.modulesPath, dataFiles: args.dataFiles.map((name) => {
|
projectDir: args.modulesPath, dataFiles: args.dataFiles.map((name) => {
|
||||||
return {
|
return {
|
||||||
@@ -61,6 +70,14 @@ export function getBlockConfigs(args = {modulesPath: '', dataFiles: []}) {
|
|||||||
};
|
};
|
||||||
}), remToPx: config.has('remToPx') ? config.get('remToPx') : 16,
|
}), remToPx: config.has('remToPx') ? config.get('remToPx') : 16,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Avoid cache conflict on Global Project css/js files.
|
||||||
|
if (updatedConfig.project) {
|
||||||
|
updatedConfig.project.css = updatedConfig.project.css ? updatedConfig.project.css + '?cache=' + Date.now() : undefined;
|
||||||
|
updatedConfig.project.js = updatedConfig.project.js ? updatedConfig.project.js + '?cache=' + Date.now() : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBlockName(name = '') {
|
export function getBlockName(name = '') {
|
||||||
@@ -98,7 +115,7 @@ export function capitalize(str) {
|
|||||||
|
|
||||||
return str
|
return str
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.split(/[ -_]/g)
|
.split(/[-_ ]/g)
|
||||||
.filter((word) => !!word)
|
.filter((word) => !!word)
|
||||||
.map((word) => {
|
.map((word) => {
|
||||||
return word.charAt(0).toUpperCase() + word.slice(1);
|
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||||
@@ -109,46 +126,33 @@ export function capitalize(str) {
|
|||||||
export async function zipProject(srcDir, outputFileName = 'dist.zip') {
|
export async function zipProject(srcDir, outputFileName = 'dist.zip') {
|
||||||
// create a file to stream archive data to.
|
// create a file to stream archive data to.
|
||||||
const output = await fsExtra.createWriteStream(outputFileName);
|
const output = await fsExtra.createWriteStream(outputFileName);
|
||||||
const archive = archiver('zip', {});
|
|
||||||
|
|
||||||
// listen for all archive data to be written
|
return new Promise((resolve, reject) => {
|
||||||
// 'close' event is fired only when a file descriptor is involved
|
// Create a file to write the archive data
|
||||||
output.on('close', function () {
|
const archive = archiver('zip', {
|
||||||
console.log(archive.pointer() + ' total bytes');
|
zlib: {level: 9} // Compression level
|
||||||
console.log('archiver has been finalized and the output file descriptor has closed.');
|
});
|
||||||
|
|
||||||
|
// Listen for errors on the archiver
|
||||||
|
archive.on('error', function (err) {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle closure of the output file stream
|
||||||
|
output.on('close', function () {
|
||||||
|
console.log(`Archive created successfully and it is ${archive.pointer()} total bytes`);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pipe archive data to the file
|
||||||
|
archive.pipe(output);
|
||||||
|
|
||||||
|
// Add files to the archive
|
||||||
|
archive.directory(srcDir, false);
|
||||||
|
|
||||||
|
// Finalize the archive - this is very important to ensure the file stream is finished
|
||||||
|
archive.finalize();
|
||||||
});
|
});
|
||||||
|
|
||||||
// This event is fired when the data source is drained no matter what was the data source.
|
|
||||||
// It is not part of this library but rather from the NodeJS Stream API.
|
|
||||||
// @see: https://nodejs.org/api/stream.html#stream_event_end
|
|
||||||
output.on('end', function () {
|
|
||||||
console.log('Data has been drained');
|
|
||||||
});
|
|
||||||
|
|
||||||
// good practice to catch warnings (ie stat failures and other non-blocking errors)
|
|
||||||
archive.on('warning', function (err) {
|
|
||||||
if (err.code === 'ENOENT') {
|
|
||||||
// log warning
|
|
||||||
} else {
|
|
||||||
// throw error
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// good practice to catch this error explicitly
|
|
||||||
archive.on('error', function (err) {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
|
|
||||||
// pipe archive data to the file
|
|
||||||
archive.pipe(output);
|
|
||||||
|
|
||||||
// append files from a subdirectory, putting its contents at the root of archive
|
|
||||||
archive.directory(srcDir, false);
|
|
||||||
|
|
||||||
// finalize the archive (ie we are done appending files but streams have to finish yet)
|
|
||||||
// 'close', 'end' or 'finish' may be fired right after calling this method so register to them beforehand
|
|
||||||
await archive.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function buildExportFiles(blockName, platform) {
|
export async function buildExportFiles(blockName, platform) {
|
||||||
@@ -160,3 +164,158 @@ export async function buildExportFiles(blockName, platform) {
|
|||||||
await buildHubspotPage(blockName)
|
await buildHubspotPage(blockName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function removeCommentsFromCss(content) {
|
||||||
|
return content.replace(/\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeCommentsFromJs(content) {
|
||||||
|
return content.replace(/\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function uploadFile(filePath, uploadUrl, validator) {
|
||||||
|
const options = {};
|
||||||
|
|
||||||
|
const contentType = mime.lookup(filePath);
|
||||||
|
if (['text/css', 'application/javascript'].includes(contentType)) {
|
||||||
|
options.encoding = 'utf8';
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = await fs.readFile(filePath, options);
|
||||||
|
|
||||||
|
if (validator) {
|
||||||
|
body = validator(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(uploadUrl, {
|
||||||
|
method: 'PUT',
|
||||||
|
body: body,
|
||||||
|
headers: {'Content-Type': contentType}
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.status !== 200;
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
const fileName = filePath.split('/').pop();
|
||||||
|
throw new Error(`Can't upload "${fileName}" file. Server permission error.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getImagesList(rootFolder, subFolder = '') {
|
||||||
|
const imagesPath = path.join(rootFolder, subFolder);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.access(imagesPath);
|
||||||
|
} catch (err) {
|
||||||
|
// Folder doesn't exist.
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const images = await fs.readdir(imagesPath);
|
||||||
|
const imagesList = [];
|
||||||
|
|
||||||
|
for (const image of images) {
|
||||||
|
const stats = await fs.stat(path.join(imagesPath, image));
|
||||||
|
|
||||||
|
if (stats.isDirectory()) {
|
||||||
|
const subImages = await getImagesList(rootFolder, image);
|
||||||
|
imagesList.push(...subImages);
|
||||||
|
} else {
|
||||||
|
imagesList.push(path.join(subFolder, image));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return imagesList;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isFileEmpty(filePath, ignoreComments = false) {
|
||||||
|
const fileContent = await fs.readFile(filePath, 'utf8');
|
||||||
|
const lines = fileContent.split('\n');
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (ignoreComments && line.trim().startsWith('//')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.trim().length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function replaceNames(content, images, uploadedImages) {
|
||||||
|
images.forEach((image, index) => {
|
||||||
|
content = content.replace(image, uploadedImages[index].fileName);
|
||||||
|
});
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getBlockFromCloud(blockName, blocksRegistry) {
|
||||||
|
const queryString = new URLSearchParams();
|
||||||
|
queryString.append('blockName', blockName);
|
||||||
|
queryString.append('includeDevConfig', 'true');
|
||||||
|
|
||||||
|
const response = await fetch(`${blocksRegistry}?${queryString.toString()}`);
|
||||||
|
const responseData = await response.json();
|
||||||
|
if (!responseData || !responseData.name) {
|
||||||
|
const message = "⚠️ Block not found, please contact administrator."
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseData.statusCode && responseData.statusCode !== 200) {
|
||||||
|
const message = ["⚠️ [ERROR]", responseData.message || "Server side error."].join(' ');
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function verifyVersion(projectPath, blocksRegistry) {
|
||||||
|
const blockJson = await readJSONFile(path.join(projectPath, `block.json`));
|
||||||
|
const blockName = getBlockName(blockJson.name);
|
||||||
|
|
||||||
|
if (typeof blockJson.version === 'undefined' || !blockName.name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This block is managed on cloud.
|
||||||
|
* Let's detect the latest version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const block = await getBlockFromCloud('@' + blockJson.name, blocksRegistry);
|
||||||
|
return block.version === blockJson.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function syncFilesWithCloud(jsonBlockPath, bs, sourceFiles = false) {
|
||||||
|
const blockJson = await readJSONFile(jsonBlockPath);
|
||||||
|
const blockName = blockJson.name.startsWith('@') ? blockJson.name : `@${blockJson.name}`;
|
||||||
|
|
||||||
|
bs.pause();
|
||||||
|
|
||||||
|
// Looks like it takes time to pause the browser-sync server, so delay(setTimeout) is necessary.
|
||||||
|
await new Promise((resolve) => setTimeout(() => resolve(), 1000));
|
||||||
|
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
const args = sourceFiles ? '--source' : '';
|
||||||
|
const createBlockModulePath = `./node_modules/@axe-web/create-block`;
|
||||||
|
|
||||||
|
// exec(`BLOCK_NAME=${blockName} node ${createBlockModulePath}/create-block.js sync ${args}`, (err, stdout, stderr) => {
|
||||||
|
exec(`node ${createBlockModulePath}/create-block.js sync ${args}`, (err, stdout, stderr) => {
|
||||||
|
if (err || stderr) {
|
||||||
|
const message = err || stderr;
|
||||||
|
console.error('Error:', message);
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(stdout);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
bs.resume();
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/swiper@8.4.5/swiper-bundle.min.css"/>
|
<link rel="stylesheet" href="https://unpkg.com/swiper@8.4.5/swiper-bundle.min.css"/>
|
||||||
|
{{#if config.project.css }} <link rel="stylesheet" href="{{ config.project.css }}">
|
||||||
|
{{/if}}
|
||||||
{{#if config.cssUrl }}
|
{{#if config.cssUrl }}
|
||||||
{{#each config.cssUrl }}
|
{{#each config.cssUrl }}
|
||||||
<link rel="stylesheet" href="{{ this }}">
|
<link rel="stylesheet" href="{{ this }}">
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
|
||||||
<script src="/scripts/dist/frame-index.min.js"></script>
|
<script src="/scripts/dist/frame-index.min.js"></script>
|
||||||
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
||||||
<script src="https://unpkg.com/swiper@8.4.5/swiper-bundle.min.js"></script>{{#if config.jsUrl }}
|
<script src="https://unpkg.com/swiper@8.4.5/swiper-bundle.min.js"></script>
|
||||||
|
{{#if config.project.js }}<script src="{{ config.project.js }}"></script>
|
||||||
|
{{/if}}
|
||||||
|
{{#if config.jsUrl }}
|
||||||
{{#each config.jsUrl }}<script src="{{ this }}"></script>
|
{{#each config.jsUrl }}<script src="{{ this }}"></script>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
<div class="page_toolbar__left"></div>
|
<div class="page_toolbar__left"></div>
|
||||||
|
|
||||||
<div class="page_toolbar__middle">
|
<div class="page_toolbar__middle">
|
||||||
<div>
|
<div style="display: none">
|
||||||
Version: <b>1rem = {{ config.version }}px</b>
|
Version: {{ config.version }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+1
-167
@@ -1,167 +1 @@
|
|||||||
window.initBlock = initBlock;
|
let e;window.initBlock=function(e="",n="",r){t=function(){document.querySelectorAll(n).forEach((e=>r(e)))},t()};let t,n={};function r(r={}){r.template&&(e=r.template),r.data&&(n=r.data),e&&function(e,n,r){const a=Handlebars.compile(e);let o;Handlebars.registerHelper("esc_attr",(function(e){return e})),Handlebars.registerHelper("esc_url",(function(e){return e})),Handlebars.registerHelper("esc_html",(function(e){return e})),Handlebars.registerHelper("base_url",(function(){return"/"}));try{o=a(n)}catch(e){o=`<div style="max-width: 1280px; margin: 1rem auto;">\n <h1 style="all: unset; font-size: 1.5rem; font-weight: bold; display: block;">Syntax Error:</h1>\n <pre style="all: unset; padding: 10px 15px; background-color: #ffe6e6; border: 1px solid red; border-radius: 0.25rem; overflow: auto; display: block; white-space: pre;">${e.toString()}</pre>\n </div>`}r.innerHTML=o,t&&t()}(e,n||{},document.getElementById("hbs-container"))}!function(){function e(){const e=new URLSearchParams(window.location.search),t={};for(const[n,r]of e)t[n]=r;return t}!function(){const t=new URLSearchParams({name:e().data||"default"});fetch(`/data?${t}`).then((e=>e.json())).then((e=>{n=e.data,r({data:n})}))}(),window.addEventListener("message",(function(e){const t=e.data,a="dataUpdate:";if("string"==typeof t&&t.startsWith(a))try{n=JSON.parse(t.substring(a.length)),r({data:n})}catch(e){console.log("Error parsing incoming data.",e)}}))}(),function(){const e=window.io.connect();e.on("error",(function(e){console.log(e)})),e.on("templateUpdate",(function(e){r({template:e.template})}))}();
|
||||||
|
|
||||||
let template;
|
|
||||||
let data = {};
|
|
||||||
let reload;
|
|
||||||
|
|
||||||
// Blocks Initialization.
|
|
||||||
function initBlock(blockName = '', selector = '', cb) {
|
|
||||||
reload = function () {
|
|
||||||
document.querySelectorAll(selector).forEach((el) => cb(el));
|
|
||||||
};
|
|
||||||
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scrollbars / Frame resizes notifications.
|
|
||||||
(function () {
|
|
||||||
let height;
|
|
||||||
|
|
||||||
handleHeightChange(); // Initial frame's height setup.
|
|
||||||
setupResizeListener(); // Listen to frame's height changes.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
function setupResizeListener() {
|
|
||||||
const resizeObserver = new ResizeObserver(handleHeightChange);
|
|
||||||
resizeObserver.observe(document.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleHeightChange() {
|
|
||||||
const updatedHeight = getCurrentHeight();
|
|
||||||
|
|
||||||
if (height === updatedHeight) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const RESIZE_CODE = 'resize:';
|
|
||||||
height = updatedHeight;
|
|
||||||
window.parent.postMessage(RESIZE_CODE + JSON.stringify({height}), '*');
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentHeight() {
|
|
||||||
return document.querySelector('#hbs-container').scrollHeight;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
// Data Updates Listeners.
|
|
||||||
(function () {
|
|
||||||
loadDataOptions();
|
|
||||||
listenToDataOptionsUpdates();
|
|
||||||
|
|
||||||
function listenToDataOptionsUpdates() {
|
|
||||||
window.addEventListener('message', function (event) {
|
|
||||||
const message = event.data;
|
|
||||||
const prefix = 'dataUpdate:';
|
|
||||||
|
|
||||||
if (typeof message !== "string" || !message.startsWith(prefix)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
data = JSON.parse(message.substring(prefix.length));
|
|
||||||
updateBlock({data});
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Error parsing incoming data.', e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getQueryParams() {
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
|
||||||
const params = {};
|
|
||||||
|
|
||||||
for (const [key, value] of urlParams) {
|
|
||||||
params[key] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadDataOptions() {
|
|
||||||
const queryParameters = new URLSearchParams({name: getQueryParams().data || 'default'});
|
|
||||||
fetch(`/data?${queryParameters}`)
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((response) => {
|
|
||||||
data = response.data; // Update state.
|
|
||||||
updateBlock({data});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
// Listen to Template updates.
|
|
||||||
(function () {
|
|
||||||
initSocket();
|
|
||||||
|
|
||||||
function initSocket() {
|
|
||||||
const socket = window.io.connect();
|
|
||||||
|
|
||||||
socket.on('error', function (err) {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
// socket.on('connect', function () {
|
|
||||||
// console.log('user connected', socket.id)
|
|
||||||
// });
|
|
||||||
|
|
||||||
socket.on('templateUpdate', function (args) {
|
|
||||||
updateBlock({template: args.template});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
function updateBlock(args = {}) {
|
|
||||||
if (args.template) {
|
|
||||||
template = args.template; // Update state.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.data) {
|
|
||||||
data = args.data; // Update state.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!template) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderBlock(template, data || {}, document.getElementById("hbs-container"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderBlock(templateHbs, jsonData, target) {
|
|
||||||
const template = Handlebars.compile(templateHbs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handlebars Helpers
|
|
||||||
*/
|
|
||||||
Handlebars.registerHelper('esc_attr', function (attr) {
|
|
||||||
return attr;
|
|
||||||
});
|
|
||||||
|
|
||||||
Handlebars.registerHelper('esc_url', function (attr) {
|
|
||||||
return attr;
|
|
||||||
});
|
|
||||||
|
|
||||||
Handlebars.registerHelper('esc_html', function (attr) {
|
|
||||||
return attr;
|
|
||||||
});
|
|
||||||
|
|
||||||
Handlebars.registerHelper('base_url', function () {
|
|
||||||
return '/';
|
|
||||||
});
|
|
||||||
|
|
||||||
let html;
|
|
||||||
|
|
||||||
try {
|
|
||||||
html = template(jsonData);
|
|
||||||
} catch (e) {
|
|
||||||
html = `<div style="max-width: 1280px; margin: 1rem auto;">
|
|
||||||
<h1 style="all: unset; font-size: 1.5rem; font-weight: bold; display: block;">Syntax Error:</h1>
|
|
||||||
<pre style="all: unset; padding: 10px 15px; background-color: #ffe6e6; border: 1px solid red; border-radius: 0.25rem; overflow: auto; display: block; white-space: pre;">${e.toString()}</pre>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
target.innerHTML = html;
|
|
||||||
if (reload) {
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=frame-index.min.js.map
|
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+15
-9917
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+21
File diff suppressed because one or more lines are too long
@@ -1,21 +0,0 @@
|
|||||||
export function setupFrameResizeListener() {
|
|
||||||
const previewFrame = getPreviewFrame();
|
|
||||||
|
|
||||||
window.addEventListener('message', function (e) {
|
|
||||||
const RESIZE_CODE = 'resize:';
|
|
||||||
if (typeof e.data !== 'string' || !e.data.startsWith(RESIZE_CODE)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = JSON.parse(e.data.substring(RESIZE_CODE.length))
|
|
||||||
let height = Number.parseInt(data.height)
|
|
||||||
if (height > 20000) {
|
|
||||||
height = 20000; // Limit max height.
|
|
||||||
}
|
|
||||||
previewFrame.style.height = height + 'px'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getPreviewFrame() {
|
|
||||||
return document.getElementById('preview_frame');
|
|
||||||
}
|
|
||||||
@@ -15,46 +15,6 @@ function initBlock(blockName = '', selector = '', cb) {
|
|||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scrollbars / Frame resizes notifications.
|
|
||||||
(function () {
|
|
||||||
let height;
|
|
||||||
const debug = false;
|
|
||||||
|
|
||||||
handleHeightChange(); // Initial frame's height setup.
|
|
||||||
setupResizeListener(); // Listen to frame's height changes.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
function setupResizeListener() {
|
|
||||||
const resizeObserver = new ResizeObserver(handleHeightChange);
|
|
||||||
resizeObserver.observe(document.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleHeightChange() {
|
|
||||||
const updatedHeight = getCurrentHeight();
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
console.log('Height Updates', 'Old vs New: ' + height, updatedHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (height === updatedHeight) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const RESIZE_CODE = 'resize:';
|
|
||||||
height = updatedHeight;
|
|
||||||
window.parent.postMessage(RESIZE_CODE + JSON.stringify({height}), '*');
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
console.log('Resize message sent: ', height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentHeight() {
|
|
||||||
return document.querySelector('#hbs-container').scrollHeight;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
// Data Updates Listeners.
|
// Data Updates Listeners.
|
||||||
(function () {
|
(function () {
|
||||||
loadDataOptions();
|
loadDataOptions();
|
||||||
|
|||||||
@@ -3,13 +3,16 @@
|
|||||||
import {setupResponsiveness} from './toolbar/responsive.jsx';
|
import {setupResponsiveness} from './toolbar/responsive.jsx';
|
||||||
import {setupPublish} from "./toolbar/publish.jsx";
|
import {setupPublish} from "./toolbar/publish.jsx";
|
||||||
import {setupDataOptions} from "./toolbar/data-options/DataOptions.jsx";
|
import {setupDataOptions} from "./toolbar/data-options/DataOptions.jsx";
|
||||||
import {getPreviewFrame, setupFrameResizeListener} from "./frame/editor.js";
|
|
||||||
|
|
||||||
const rootAttributes = {
|
const rootAttributes = {
|
||||||
previewFrame: getPreviewFrame(),
|
previewFrame: getPreviewFrame(),
|
||||||
};
|
};
|
||||||
|
|
||||||
setupFrameResizeListener();
|
// setupFrameResizeListener();
|
||||||
setupResponsiveness(rootAttributes);
|
setupResponsiveness(rootAttributes);
|
||||||
setupDataOptions(rootAttributes);
|
setupDataOptions(rootAttributes);
|
||||||
setupPublish(rootAttributes);
|
setupPublish(rootAttributes);
|
||||||
|
|
||||||
|
function getPreviewFrame() {
|
||||||
|
return document.getElementById('preview_frame');
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React, {useState} from "react";
|
||||||
|
import * as ReactDOM from "react-dom/client";
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
const wrapper = document.querySelector('#screen');
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(wrapper);
|
||||||
|
const html = (<SyncScreen/>);
|
||||||
|
|
||||||
|
root.render(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SyncScreen() {
|
||||||
|
const [loading, setLoading] = useState(null);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
return <>
|
||||||
|
|
||||||
|
<section className="container py-5">
|
||||||
|
<h1 style={{marginBottom: '2rem'}}>Oops... Block not in sync.</h1>
|
||||||
|
{error && <p className="alert alert-danger">{error}</p>}
|
||||||
|
|
||||||
|
{loading ?
|
||||||
|
<>
|
||||||
|
{loading === 'syncing' &&
|
||||||
|
<p>Version upgrade in progress...</p>
|
||||||
|
}
|
||||||
|
<p>Please wait...</p>
|
||||||
|
</>
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
<p>Your version of the block is not in sync with the cloud (not latest version).<br/>
|
||||||
|
Would you like to update it?</p>
|
||||||
|
<div className="options">
|
||||||
|
<button className="btn btn-primary" style={{marginRight: '0.5rem'}} onClick={runSyncLogic}>Yes, Update to
|
||||||
|
Latest
|
||||||
|
</button>
|
||||||
|
<button className="btn btn-secondary" onClick={ignoreVersionSync}>Ignore</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</>
|
||||||
|
|
||||||
|
async function ignoreVersionSync() {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
let data = {};
|
||||||
|
try {
|
||||||
|
const response = await fetch('/sync', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ignore: true}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
data = await response.json();
|
||||||
|
} catch (err) {
|
||||||
|
setError('Error: ' + err.message);
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.status !== 200) {
|
||||||
|
setError(data.message);
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => window.location.reload(), 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runSyncLogic() {
|
||||||
|
setLoading('syncing');
|
||||||
|
|
||||||
|
let data = {};
|
||||||
|
try {
|
||||||
|
const response = await fetch('/sync', {method: 'POST'});
|
||||||
|
data = await response.json();
|
||||||
|
} catch (err) {
|
||||||
|
setError('Error: ' + err.message);
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.status !== 200) {
|
||||||
|
setError(data.message);
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => window.location.reload(), 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
@@ -125,12 +125,13 @@ function DataOptions(props = {}) {
|
|||||||
return fetch(url, requestOptions)
|
return fetch(url, requestOptions)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(result => {
|
.then(result => {
|
||||||
|
console.log(result)
|
||||||
if (result.statusCode !== 200) {
|
if (result.statusCode !== 200) {
|
||||||
throw new Error(result.message);
|
throw new Error(result.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = result.variation;
|
const data = result.variation;
|
||||||
updateState({dataText: JSON.stringify(data, null, 2), data});
|
updateState({dataText: JSON.stringify(data, null, 2), data, errorMessage: null, loading: false});
|
||||||
updateIframe(data);
|
updateIframe(data);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ function Responsive(props = {}) {
|
|||||||
function updateController() {
|
function updateController() {
|
||||||
let frameBreakpoint = breakpoint;
|
let frameBreakpoint = breakpoint;
|
||||||
if (typeof frameBreakpoint !== 'string') {
|
if (typeof frameBreakpoint !== 'string') {
|
||||||
frameBreakpoint = frameBreakpoint + 'px';
|
const scrollbarWidth = 15;
|
||||||
|
frameBreakpoint = (scrollbarWidth + frameBreakpoint) + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
previewFrame.style.setProperty('--breakpoint', frameBreakpoint);
|
previewFrame.style.setProperty('--breakpoint', frameBreakpoint);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
.preview {
|
.preview {
|
||||||
overflow-y: scroll;
|
|
||||||
height: calc(100% - var(--top_panel_height));
|
height: calc(100% - var(--top_panel_height));
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -9,17 +8,14 @@
|
|||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
//height: 100%;
|
||||||
|
|
||||||
--top_spacing: 0px;
|
--top_spacing: 0px;
|
||||||
--breakpoint_top_spacing: 30px;
|
--breakpoint_top_spacing: 30px;
|
||||||
|
|
||||||
margin-top: var(--top_spacing);
|
margin-top: var(--top_spacing);
|
||||||
height: 100%;
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
||||||
border: 0;
|
border: 0;
|
||||||
outline: 1px solid #E2E8F0;
|
|
||||||
|
|
||||||
transition: max-width .3s ease-in-out, width .3s ease-in-out, margin-top .3s ease-in-out;
|
transition: max-width .3s ease-in-out, width .3s ease-in-out, margin-top .3s ease-in-out;
|
||||||
|
|
||||||
&.has-breakpoint {
|
&.has-breakpoint {
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
.swiper {
|
|
||||||
&-slide {
|
|
||||||
width: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-wrapper {
|
|
||||||
height: initial;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -114,7 +114,6 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.preview {
|
.preview {
|
||||||
overflow-y: scroll;
|
|
||||||
height: calc(100% - var(--top_panel_height));
|
height: calc(100% - var(--top_panel_height));
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -127,10 +126,8 @@ body {
|
|||||||
--top_spacing: 0px;
|
--top_spacing: 0px;
|
||||||
--breakpoint_top_spacing: 30px;
|
--breakpoint_top_spacing: 30px;
|
||||||
margin-top: var(--top_spacing);
|
margin-top: var(--top_spacing);
|
||||||
height: 100%;
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: 0;
|
border: 0;
|
||||||
outline: 1px solid #E2E8F0;
|
|
||||||
transition: max-width 0.3s ease-in-out, width 0.3s ease-in-out, margin-top 0.3s ease-in-out;
|
transition: max-width 0.3s ease-in-out, width 0.3s ease-in-out, margin-top 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
#preview_frame.has-breakpoint {
|
#preview_frame.has-breakpoint {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"sourceRoot":"","sources":["page--main.scss","_buttons.scss","_overlay.scss","_page--preview.scss"],"names":[],"mappings":"AAAA;EACE;EACA;;;AAGF;EACE;EACA;EAEA;;;ACTF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;;AC5BJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AFIF;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EAEA;EACA;EACA;EAEA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAKF;EADF;IAEI;;;AAKN;EAEE;EACA;EACA;EACA;;AAGF;EACE;;;AGlFJ;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EAEA;EACA;EAEA;;AAEA;EACE;EAEA;EACA;;;AH6DJ;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EAEE;;;AAGF;EAEE;EACA","file":"page--main.css"}
|
{"version":3,"sourceRoot":"","sources":["page--main.scss","_buttons.scss","_overlay.scss","_page--preview.scss"],"names":[],"mappings":"AAAA;EACE;EACA;;;AAGF;EACE;EACA;EAEA;;;ACTF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;;AC5BJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AFIF;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EAEA;EACA;EACA;EAEA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAKF;EADF;IAEI;;;AAKN;EAEE;EACA;EACA;EACA;;AAGF;EACE;;;AGlFJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACA;;AAEA;EACE;EAEA;EACA;;;AHiEJ;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EAEE;;;AAGF;EAEE;EACA","file":"page--main.css"}
|
||||||
@@ -2,24 +2,8 @@ body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
min-height: 100%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
main .swiper-slide {
|
|
||||||
width: initial;
|
|
||||||
}
|
|
||||||
main .swiper-wrapper {
|
|
||||||
height: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body--iframe {
|
.body--iframe {
|
||||||
overflow-y: hidden;
|
overflow-y: scroll;
|
||||||
}
|
|
||||||
.body--iframe main {
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.fullscreen_layout {
|
.fullscreen_layout {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"sourceRoot":"","sources":["page--view.scss","_page--view-swiper.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;;ACPA;EACE;;AAGF;EACE;;;ADSJ;EACE;;AAEA;EAGE;;;AAIJ;EACE;EACA;EACA;EACA","file":"page--view.css"}
|
{"version":3,"sourceRoot":"","sources":["page--view.scss"],"names":[],"mappings":"AAAA;EACE;;;AAIF;EACE;;;AAGF;EACE;EACA;EACA;EACA","file":"page--view.css"}
|
||||||
@@ -2,25 +2,9 @@ body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
min-height: 100%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
|
|
||||||
// Fixes scrolling issues of swiperJS. Should be included in all projects.
|
|
||||||
@import "page--view-swiper";
|
|
||||||
}
|
|
||||||
|
|
||||||
// iFrame mode
|
// iFrame mode
|
||||||
.body--iframe {
|
.body--iframe {
|
||||||
overflow-y: hidden;
|
overflow-y: scroll;
|
||||||
|
|
||||||
main {
|
|
||||||
// If you change to "overflow: initial", the margin-top/bottom of first/last element will be not included.
|
|
||||||
// Test on fresh block setup where heading has margin-top.
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.fullscreen_layout {
|
.fullscreen_layout {
|
||||||
@@ -29,4 +13,3 @@ main {
|
|||||||
background-image: url('https://i.ibb.co/pjwL8D1/shapelined-JBKdviwe-XI-unsplash.jpg');
|
background-image: url('https://i.ibb.co/pjwL8D1/shapelined-JBKdviwe-XI-unsplash.jpg');
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Block Development Tool</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="screen">Loading...</div>
|
||||||
|
|
||||||
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
|
<script src="/scripts/dist/sync.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Generated
+116
-8123
File diff suppressed because it is too large
Load Diff
+8
-5
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@axe-web/block-dev-tool",
|
"name": "@axe-web/block-dev-tool",
|
||||||
"version": "1.0.27",
|
"version": "1.0.36",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "AXE-WEB",
|
"name": "AXE-WEB",
|
||||||
"email": "office@axe-web.com",
|
"email": "office@axe-web.com",
|
||||||
"url": "https://axe-web.com/"
|
"url": "https://axe-web.com/"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"info": "NODE_ENV=development BLOCK_NAME=header MODULE_PATH= node debug.js",
|
"info": "BLOCK_NAME=ebooks-resources MODULE_PATH= node debug.js",
|
||||||
"dev": "NODE_ENV=development BLOCK_NAME=header MODULE_PATH= node server.js",
|
"dev": "BLOCK_NAME=ebooks-resources MODULE_PATH= node server.js",
|
||||||
"build-platform": "NODE_ENV=development BLOCK_NAME=header MODULE_PATH= node ./build.js",
|
"build-platform": "BLOCK_NAME=ebooks-resources MODULE_PATH= node ./build.js",
|
||||||
"dev-dev-tool": "NODE_ENV=development rollup --config rollup.config.js --watch",
|
"dev-dev-tool": "rollup --config rollup.config.js --watch",
|
||||||
"build-dev-tool": "rollup --config rollup.config.js"
|
"build-dev-tool": "rollup --config rollup.config.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -19,8 +19,10 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@axe-web/create-block": "^1.1.30",
|
||||||
"@braintree/sanitize-url": "^6.0.0",
|
"@braintree/sanitize-url": "^6.0.0",
|
||||||
"archiver": "^5.3.1",
|
"archiver": "^5.3.1",
|
||||||
|
"body-parser": "^1.20.2",
|
||||||
"browser-sync": "^2.27.9",
|
"browser-sync": "^2.27.9",
|
||||||
"config": "^3.3.7",
|
"config": "^3.3.7",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
@@ -37,6 +39,7 @@
|
|||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"mem-fs": "^2.2.1",
|
"mem-fs": "^2.2.1",
|
||||||
"mem-fs-editor": "^9.5.0",
|
"mem-fs-editor": "^9.5.0",
|
||||||
|
"mime-types": "^2.1.35",
|
||||||
"ngrok": "^5.0.0-beta.2",
|
"ngrok": "^5.0.0-beta.2",
|
||||||
"node-fetch": "^3.2.10",
|
"node-fetch": "^3.2.10",
|
||||||
"open": "^8.4.0",
|
"open": "^8.4.0",
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ export async function createDistFolder(blockName, projectPath = '') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getBlockFields(block = {}, type = 'content') {
|
export function getBlockFields(block = {}, type = 'content') {
|
||||||
|
if (!block['field_groups']) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const fields_group = block['field_groups'].find((group) => group.name === type);
|
const fields_group = block['field_groups'].find((group) => group.name === type);
|
||||||
const fields = [];
|
const fields = [];
|
||||||
|
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ class Component_Builder {
|
|||||||
$this->register_default_handlebar_helpers();
|
$this->register_default_handlebar_helpers();
|
||||||
|
|
||||||
$this->add_handlebar( 'base_url', function ( $context ) {
|
$this->add_handlebar( 'base_url', function ( $context ) {
|
||||||
$path = join( '/', [ 'blocks', $this->block_project, $this->block_name, 'templates' ] );
|
$path = join( '/', [ $this->block_project, $this->block_name, 'templates' ] );
|
||||||
return plugins_url( $path . '/', 'axeweb-blocks-library/axeweb-blocks-library.php' );
|
return join( '/', [ get_site_url(),'wp-content', 'axe-web-blocks', $path, '' ] );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,13 @@
|
|||||||
|
|
||||||
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>;
|
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>;
|
||||||
|
|
||||||
class <%= blockClassModel %>_Component <% if (isComponentManager || isElementor) { %>extends \Core\Component <% } %>{
|
class <%= blockClassModel %>_Component extends \Core\Component {
|
||||||
const VERSION = '<%= version %>';
|
const VERSION = '<%= version %>';
|
||||||
public $block_project = '<%= ownerFilename %>';
|
public $block_project = '<%= ownerFilename %>';
|
||||||
public $block_name = '<%= blockFilename %>';
|
public $block_name = '<%= blockFilename %>';
|
||||||
public $hook_prefix = 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>';
|
public $hook_prefix = 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>';
|
||||||
|
|
||||||
<% if (!isComponentManager && !isElementor) { %>public function __construct() {
|
function register_assets(): void {
|
||||||
parent::__construct();
|
|
||||||
// add_action( 'wp_enqueue_scripts', [ $this, 'register_assets' ] );
|
|
||||||
add_action( 'after_setup_theme', [ $this, 'register_assets' ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
<% } %>function register_assets(): void {
|
|
||||||
$base_path = plugin_dir_url( __FILE__ ); // In Plugins
|
$base_path = plugin_dir_url( __FILE__ ); // In Plugins
|
||||||
// $base_path = get_template_directory_uri() . '/components/partials/<%= blockFilename %>/'; // In Theme
|
// $base_path = get_template_directory_uri() . '/components/partials/<%= blockFilename %>/'; // In Theme
|
||||||
|
|
||||||
@@ -22,12 +16,14 @@ class <%= blockClassModel %>_Component <% if (isComponentManager || isElementor)
|
|||||||
wp_register_style( 'block-<%= blockFilename %>', $base_path . 'templates/styles/<%= blockFilename %>.min.css', $style_deps, self::VERSION );
|
wp_register_style( 'block-<%= blockFilename %>', $base_path . 'templates/styles/<%= blockFilename %>.min.css', $style_deps, self::VERSION );
|
||||||
|
|
||||||
$script_deps = apply_filters( 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>::script_deps', [ 'assets-script' ] );
|
$script_deps = apply_filters( 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>::script_deps', [ 'assets-script' ] );
|
||||||
wp_register_script( 'block-<%= blockFilename %>', $base_path . 'templates/scripts/<%= blockFilename %>.min.js', $script_deps, self::VERSION, true );<% if (!isElementor) { %>
|
wp_register_script( 'block-<%= blockFilename %>', $base_path . 'templates/scripts/<%= blockFilename %>.min.js', $script_deps, self::VERSION, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepare_for_print() {
|
||||||
if ( ! is_admin() ) {
|
if ( ! is_admin() ) {
|
||||||
wp_enqueue_style( 'block-<%= blockFilename %>' );
|
wp_enqueue_style( 'block-<%= blockFilename %>' );
|
||||||
wp_enqueue_script( 'block-<%= blockFilename %>' );
|
wp_enqueue_script( 'block-<%= blockFilename %>' );
|
||||||
}<% } %>
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_content( $args = [] ): string {
|
public function get_content( $args = [] ): string {
|
||||||
@@ -37,8 +33,8 @@ class <%= blockClassModel %>_Component <% if (isComponentManager || isElementor)
|
|||||||
|
|
||||||
$output = ( include( __DIR__ . '/templates/<%= blockFilename %>.template.php' ) )( $args, self::class );
|
$output = ( include( __DIR__ . '/templates/<%= blockFilename %>.template.php' ) )( $args, self::class );
|
||||||
|
|
||||||
return apply_filters( 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>::content', $output );
|
return apply_filters( 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>::content', $output, $args );
|
||||||
}<% if (isElementor) { %>
|
}
|
||||||
|
|
||||||
function register_custom_logic(): void {
|
function register_custom_logic(): void {
|
||||||
add_action( 'elementor/widgets/widgets_registered', [ $this, 'register_elementor_widget' ] );
|
add_action( 'elementor/widgets/widgets_registered', [ $this, 'register_elementor_widget' ] );
|
||||||
@@ -47,9 +43,25 @@ class <%= blockClassModel %>_Component <% if (isComponentManager || isElementor)
|
|||||||
function register_elementor_widget( $widgets_manager ): void {
|
function register_elementor_widget( $widgets_manager ): void {
|
||||||
require_once "helpers/<%= blockClassModel %>_Elementor_Widget.php";
|
require_once "helpers/<%= blockClassModel %>_Elementor_Widget.php";
|
||||||
$widgets_manager->register_widget_type( new Helpers\<%= blockClassModel %>_Elementor_Widget() );
|
$widgets_manager->register_widget_type( new Helpers\<%= blockClassModel %>_Elementor_Widget() );
|
||||||
}<% } %>
|
}
|
||||||
|
|
||||||
|
function register_acf_block() {
|
||||||
|
$this->register_block( __DIR__ . "/<%= blockFilename %>.block.json", [
|
||||||
|
'style_assets' => [
|
||||||
|
[
|
||||||
|
'name' => 'block-<%= blockFilename %>',
|
||||||
|
'url' => $this->get_assets_path_url( 'templates/styles/<%= blockFilename %>.min.css' ),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'script_assets' => [
|
||||||
|
[
|
||||||
|
'name' => 'block-<%= blockFilename %>',
|
||||||
|
'url' => $this->get_assets_path_url( 'templates/scripts/<%= blockFilename %>.min.js' ),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<% if (isComponentManager) { %><%= blockClassModel %>_Component::get_instance();<% } else {
|
<%= blockClassModel %>_Component::get_instance();
|
||||||
%>new <%= blockClassModel %>_Component();<% } %>
|
// new <%= blockClassModel %>_Component();
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>;
|
|
||||||
|
|
||||||
class <%= blockClassModel %>_Component extends \Core\Component {
|
|
||||||
const VERSION = '<%= version %>';
|
|
||||||
public $block_project = '<%= ownerFilename %>';
|
|
||||||
public $block_name = '<%= blockFilename %>';
|
|
||||||
public $hook_prefix = 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>';
|
|
||||||
|
|
||||||
public function get_content( $args = [] ): string {
|
|
||||||
$default_args = apply_filters( 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>::default_args', [] ); // Not really practical.
|
|
||||||
|
|
||||||
$args = apply_filters( 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>::prepare_args', array_merge( $default_args, $args ) );
|
|
||||||
|
|
||||||
$output = ( include( __DIR__ . '/templates/<%= blockFilename %>.template.php' ) )( $args, self::class );
|
|
||||||
|
|
||||||
return apply_filters( 'axeweb_blocks/<%= ownerFilename %>/<%= blockFilename %>::content', $output );
|
|
||||||
}
|
|
||||||
<% if (!include_acf_block && !include_native_gutenberg_block) { %>function register_assets(): void {
|
|
||||||
$version = get_plugin_data( __DIR__ . "/../../scytale-custom-blocks.php" )['Version']; // In Plugins
|
|
||||||
// $version = \Core\Global_Functions::get_current_version_number(); // In Theme
|
|
||||||
|
|
||||||
// $base_path = get_template_directory_uri() . '/components/partials/<%= blockFilename %>/';
|
|
||||||
wp_enqueue_style( 'block-<%= blockFilename %>', plugins_url( 'templates/styles/<%= blockFilename %>.min.css', __FILE__ ), ['assets-style'], self::VERSION );<% if (include_script) { %>
|
|
||||||
wp_enqueue_script( 'block-<%= blockFilename %>', plugins_url( 'templates/scripts/<%= blockFilename %>.min.js', __FILE__ ), ['assets-script'], self::VERSION, true );<% } %>
|
|
||||||
|
|
||||||
wp_enqueue_script( 'script-block-<%= blockFilename %>' );
|
|
||||||
}<% } %>
|
|
||||||
<% if (include_acf_block) { %> function register_acf_block() {
|
|
||||||
$this->register_block( __DIR__ . "/<%= blockFilename %>.block.json", [
|
|
||||||
'style_assets' => [
|
|
||||||
[
|
|
||||||
'name' => '<%= blockFilename %>',
|
|
||||||
'url' => plugins_url( 'templates/styles/<%= blockFilename %>.min.css', __FILE__ ),
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'script_assets' => [
|
|
||||||
[
|
|
||||||
'name' => '<%= blockFilename %>',
|
|
||||||
'url' => plugins_url( 'templates/scripts/<%= blockFilename %>.min.js', __FILE__ ),
|
|
||||||
]
|
|
||||||
]
|
|
||||||
] );
|
|
||||||
}
|
|
||||||
<% } %><% if (include_native_gutenberg_block) { %> function register_native_gutenberg_block() {
|
|
||||||
register_block_type( __DIR__ . '/templates/gutenberg-block/block.json' );<% if (include_script) { %>
|
|
||||||
|
|
||||||
add_action( 'wp_enqueue_scripts', function () {
|
|
||||||
$asset_file_front = include( plugin_dir_path( __FILE__ ) . '/templates/gutenberg-block/build/front.asset.php' );
|
|
||||||
wp_enqueue_script(
|
|
||||||
'gutenberg-<%= blockFilename %>-scripts-front',
|
|
||||||
plugins_url( 'templates/gutenberg-block/build/front.js', __FILE__ ),
|
|
||||||
$asset_file_front['dependencies'],
|
|
||||||
$asset_file_front['version'],
|
|
||||||
true
|
|
||||||
);
|
|
||||||
} );<% } %>
|
|
||||||
}<% } %>
|
|
||||||
}
|
|
||||||
|
|
||||||
<%= blockClassModel %>_Component::get_instance();
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>\Helpers;
|
|
||||||
|
|
||||||
class <%= blockClassModel %>_API {
|
|
||||||
|
|
||||||
static function prepare_args( $args = [] ) {
|
|
||||||
|
|
||||||
// $args = array_merge( [], $args );
|
|
||||||
|
|
||||||
return $args;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>\Helpers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Component's default args.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class <%= blockClassModel %>_Defaults {
|
|
||||||
public static function default_args(): array {
|
|
||||||
$args = <%- defaultData %>;
|
|
||||||
|
|
||||||
// $args['base_url'] = \Core\Global_Functions::get_file_url( __DIR__ . '/../templates/' );
|
|
||||||
|
|
||||||
return $args;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>\Helpers;
|
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>\Helpers;
|
||||||
|
|
||||||
class <%= blockClassModel %>_Elementor_Widget extends \Elementor\Widget_Base {
|
class <%= blockClassModel %>_Elementor_Widget extends \Elementor\Widget_Base {
|
||||||
|
use \Core\Traits\Elementor_Widget;
|
||||||
|
|
||||||
const PLUGIN_NAME = '<%= blockFilename %>';
|
const PLUGIN_NAME = '<%= blockFilename %>';
|
||||||
|
|
||||||
public function get_name() {
|
public function get_name() {
|
||||||
@@ -35,12 +37,8 @@ class <%= blockClassModel %>_Elementor_Widget extends \Elementor\Widget_Base {
|
|||||||
|
|
||||||
$component = new \AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>\<%= blockClassModel %>_Component();
|
$component = new \AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>\<%= blockClassModel %>_Component();
|
||||||
|
|
||||||
$args = self::prepare( $settings );
|
$args = $this->prepare( $settings );
|
||||||
$component->render( $args );
|
$component->render( $args );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function prepare( $args ): array {
|
|
||||||
// Prepare $args for render function.
|
|
||||||
return $args;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import {mkdir, copyFile} from "fs/promises";
|
import fs, {mkdir, copyFile} from "fs/promises";
|
||||||
import {capitalize, createFiles, getBlockName, getConfigs, readJSONFile} from "../../helpers.js";
|
import {capitalize, createFiles, getBlockName, getConfigs, readJSONFile} from "../../helpers.js";
|
||||||
import {fileURLToPath} from 'url';
|
import {fileURLToPath} from 'url';
|
||||||
import {copy} from "fs-extra";
|
import {copy} from "fs-extra";
|
||||||
@@ -10,10 +10,6 @@ const __filename = fileURLToPath(import.meta.url);
|
|||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
export async function buildWordPress(blockName, args = {}) {
|
export async function buildWordPress(blockName, args = {}) {
|
||||||
const isBlock = args.platform === 'wordpress-acf-block';
|
|
||||||
const isElementor = args.platform === 'wordpress-elementor';
|
|
||||||
const isComponentManager = args.platform === 'wordpress-component-manager'
|
|
||||||
|
|
||||||
const {modulesPath, projectPath} = getConfigs();
|
const {modulesPath, projectPath} = getConfigs();
|
||||||
|
|
||||||
const distPath = path.join(projectPath, 'exports', args.platform);
|
const distPath = path.join(projectPath, 'exports', args.platform);
|
||||||
@@ -37,12 +33,7 @@ export async function buildWordPress(blockName, args = {}) {
|
|||||||
ownerClass: owner.replace(/ /ig, '_'),
|
ownerClass: owner.replace(/ /ig, '_'),
|
||||||
ownerFilename: owner.toLowerCase().replace(/ /ig, '-'),
|
ownerFilename: owner.toLowerCase().replace(/ /ig, '-'),
|
||||||
templateFormat: 'php',
|
templateFormat: 'php',
|
||||||
include_acf_block: isBlock,
|
|
||||||
include_native_gutenberg_block: false,
|
|
||||||
include_script: true,
|
include_script: true,
|
||||||
include_elementor_widget: isElementor,
|
|
||||||
isElementor,
|
|
||||||
isComponentManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await copyFile(blockFilePath, path.join(distPath, data.blockFilename + '.block.json'));
|
await copyFile(blockFilePath, path.join(distPath, data.blockFilename + '.block.json'));
|
||||||
@@ -68,58 +59,37 @@ export async function buildWordPress(blockName, args = {}) {
|
|||||||
path.join(distPath, 'templates', 'scripts', `${data.blockFilename}.min.js`),
|
path.join(distPath, 'templates', 'scripts', `${data.blockFilename}.min.js`),
|
||||||
);
|
);
|
||||||
|
|
||||||
await copy(
|
try {
|
||||||
path.join(projectPath, 'src', 'images'),
|
const imagesPath = path.join(projectPath, 'src', 'images');
|
||||||
path.join(distPath, 'templates', 'images'),
|
await fs.access(imagesPath);
|
||||||
);
|
|
||||||
|
await copy(
|
||||||
|
path.join(imagesPath),
|
||||||
|
path.join(distPath, 'templates', 'images'),
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
// Folder doesn't exist.
|
||||||
|
}
|
||||||
|
|
||||||
const phpDataObject = await execPHPFile(path.join(phpGeneratorPath, 'build.php'), 'jsonToPhp', {
|
const phpDataObject = await execPHPFile(path.join(phpGeneratorPath, 'build.php'), 'jsonToPhp', {
|
||||||
json: await readJSONFile(path.join(projectPath, 'data', 'default.json'), "utf8"),
|
json: await readJSONFile(path.join(projectPath, 'data', 'default.json'), "utf8"),
|
||||||
});
|
});
|
||||||
|
|
||||||
// await createFiles(Object.assign({}, data, {defaultData: phpDataObject}), [{
|
await createFiles(data, [{
|
||||||
// from: `templates/helpers/Template_Defaults.php`,
|
from: `templates/helpers/Template_Elementor_Widget.php`,
|
||||||
// to: `helpers/${data.blockClassModel}_Defaults.php`,
|
to: `helpers/${data.blockClassModel}_Elementor_Widget.php`,
|
||||||
// }], {
|
}], {
|
||||||
// pathDist: distPath,
|
pathDist: distPath,
|
||||||
// generatorsPath: path.join(__dirname),
|
generatorsPath: path.join(__dirname)
|
||||||
// });
|
});
|
||||||
|
|
||||||
if (isElementor) {
|
await createFiles(data, [{
|
||||||
await createFiles(data, [{
|
from: `templates/Template_Basic_Component.php`,
|
||||||
from: `templates/helpers/Template_Elementor_Widget.php`,
|
to: `${data.blockClassModel}_Component.php`,
|
||||||
to: `helpers/${data.blockClassModel}_Elementor_Widget.php`,
|
}], {
|
||||||
}], {
|
pathDist: distPath,
|
||||||
pathDist: distPath,
|
generatorsPath: path.join(__dirname)
|
||||||
generatorsPath: path.join(__dirname)
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isBlock) {
|
|
||||||
await createFiles(data, [{
|
|
||||||
from: `templates/Template_Component.php`,
|
|
||||||
to: `${data.blockClassModel}_Component.php`,
|
|
||||||
}], {
|
|
||||||
pathDist: distPath,
|
|
||||||
generatorsPath: path.join(__dirname)
|
|
||||||
});
|
|
||||||
|
|
||||||
// await createFiles(data, [{
|
|
||||||
// from: `templates/helpers/Template_API.php`,
|
|
||||||
// to: `helpers/${data.blockClassModel}_API.php`,
|
|
||||||
// }], {
|
|
||||||
// pathDist: distPath,
|
|
||||||
// generatorsPath: path.join(__dirname)
|
|
||||||
// });
|
|
||||||
} else {
|
|
||||||
await createFiles(data, [{
|
|
||||||
from: `templates/Template_Basic_Component.php`,
|
|
||||||
to: `${data.blockClassModel}_Component.php`,
|
|
||||||
}], {
|
|
||||||
pathDist: distPath,
|
|
||||||
generatorsPath: path.join(__dirname)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function execCommand(cmd = '') {
|
export function execCommand(cmd = '') {
|
||||||
|
|||||||
@@ -47,4 +47,26 @@ export default [{
|
|||||||
commonjs(),
|
commonjs(),
|
||||||
!devMode && terser()
|
!devMode && terser()
|
||||||
]
|
]
|
||||||
|
}, {
|
||||||
|
input: 'layouts/scripts/sync.jsx',
|
||||||
|
output: {
|
||||||
|
file: 'layouts/scripts/dist/sync.min.js',
|
||||||
|
sourcemap: devMode
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({
|
||||||
|
extensions: [".js"],
|
||||||
|
}),
|
||||||
|
replace({
|
||||||
|
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||||
|
preventAssignment: true,
|
||||||
|
}),
|
||||||
|
babel({
|
||||||
|
compact: false,
|
||||||
|
babelHelpers: 'bundled',
|
||||||
|
presets: ["@babel/preset-react"],
|
||||||
|
}),
|
||||||
|
commonjs(),
|
||||||
|
!devMode && terser()
|
||||||
|
]
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -19,11 +19,27 @@ import open from "open";
|
|||||||
import {sanitizeUrl} from "@braintree/sanitize-url";
|
import {sanitizeUrl} from "@braintree/sanitize-url";
|
||||||
import sanitizeHtml from 'sanitize-html';
|
import sanitizeHtml from 'sanitize-html';
|
||||||
import {escape} from "lodash-es";
|
import {escape} from "lodash-es";
|
||||||
import {getBlockData, getBlockConfigs, getConfigs, readJSONFile, zipProject} from "./helpers.js";
|
import {
|
||||||
|
getBlockConfigs,
|
||||||
|
getBlockData,
|
||||||
|
getBlockName,
|
||||||
|
getConfigs,
|
||||||
|
getImagesList,
|
||||||
|
isFileEmpty,
|
||||||
|
readJSONFile,
|
||||||
|
removeCommentsFromCss,
|
||||||
|
removeCommentsFromJs,
|
||||||
|
replaceNames,
|
||||||
|
syncFilesWithCloud,
|
||||||
|
uploadFile,
|
||||||
|
verifyVersion,
|
||||||
|
zipProject
|
||||||
|
} from "./helpers.js";
|
||||||
import PluginError from 'plugin-error';
|
import PluginError from 'plugin-error';
|
||||||
import {Server} from "socket.io";
|
import {Server} from "socket.io";
|
||||||
import {createServer} from 'http';
|
import {createServer} from 'http';
|
||||||
import {authtoken, connect} from "ngrok";
|
// import {authtoken, connect} from "ngrok";
|
||||||
|
import bodyParser from "body-parser";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
@@ -33,7 +49,8 @@ const {isDev, modulesPath, projectPath, developmentBlockName} = getConfigs();
|
|||||||
const blocksRegistry = isDev ? 'http://localhost:3020' : PRODUCTION_REGISTRY_URL;
|
const blocksRegistry = isDev ? 'http://localhost:3020' : PRODUCTION_REGISTRY_URL;
|
||||||
const DevToolToken = 'D9lgz0TvzXCnp0xnwVBL109DaAR6Puk6F7YewDhgmP8='; // Temporary token for development purposes.
|
const DevToolToken = 'D9lgz0TvzXCnp0xnwVBL109DaAR6Puk6F7YewDhgmP8='; // Temporary token for development purposes.
|
||||||
|
|
||||||
const dataFiles = prepareListOfDataFiles(await fs.readdir(path.join(projectPath, 'data')));
|
const dataFiles = await getDataFiles(projectPath);
|
||||||
|
const DEFAULT_VIEW_LAYOUT = 'alignfull';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State
|
* State
|
||||||
@@ -43,12 +60,21 @@ let port = 3000; // This variable is used in `*.hbs` and it will be updated once
|
|||||||
let previewFrameUrl = `/`; // This variable is used in `*.hbs` and it will be updated once BrowserSync is ready.
|
let previewFrameUrl = `/`; // This variable is used in `*.hbs` and it will be updated once BrowserSync is ready.
|
||||||
let shareUrl = '';
|
let shareUrl = '';
|
||||||
const sessions = [];
|
const sessions = [];
|
||||||
|
let ignoreVersionSync = false;
|
||||||
|
let bs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init server
|
* Init server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
// parse application/x-www-form-urlencoded
|
||||||
|
app.use(bodyParser.urlencoded({extended: false}))
|
||||||
|
|
||||||
|
// parse application/json
|
||||||
|
app.use(bodyParser.json())
|
||||||
|
|
||||||
const httpServer = createServer(app);
|
const httpServer = createServer(app);
|
||||||
initSessionsServer(httpServer);
|
initSessionsServer(httpServer);
|
||||||
|
|
||||||
@@ -77,58 +103,84 @@ app.set('views', path.join(modulesPath, 'layouts'));
|
|||||||
// Routes
|
// Routes
|
||||||
//
|
//
|
||||||
|
|
||||||
app.get('/', (req, res) => {
|
app.get('/', async (req, res, next) => {
|
||||||
const data = getBlockConfigs({modulesPath, dataFiles});
|
const data = getBlockConfigs({modulesPath, dataFiles});
|
||||||
if (data.error && data.errorMessage) {
|
if (data.error && data.errorMessage) {
|
||||||
return res.send(data.errorMessage);
|
return res.send(data.errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseView = config.has('baseView') ? config.get('baseView') : 'container';
|
const baseView = config.has('baseView') ? config.get('baseView') : DEFAULT_VIEW_LAYOUT;
|
||||||
const baseViewUrl = `view/${baseView}`;
|
const baseViewUrl = `view/${baseView}`;
|
||||||
|
|
||||||
data.helpers = {
|
data.helpers = {
|
||||||
include_partial: (filesPath) => handlebarLayoutsPath(modulesPath, filesPath),
|
include_partial: (filesPath) => handlebarLayoutsPath(modulesPath, filesPath),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const verifiedVersion = await verifyVersion(projectPath, blocksRegistry);
|
||||||
|
if (!verifiedVersion && !ignoreVersionSync) {
|
||||||
|
return res.render('sync', data);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
const errorMessage = "Can't verify block version.";
|
||||||
|
console.log(errorMessage, err);
|
||||||
|
return next(new Error(errorMessage));
|
||||||
|
}
|
||||||
|
|
||||||
data.baseView = baseView;
|
data.baseView = baseView;
|
||||||
data.port = `/${baseViewUrl}`;
|
data.port = `/${baseViewUrl}`;
|
||||||
data.previewFrameUrl = `${previewFrameUrl}/${baseViewUrl}`;
|
data.previewFrameUrl = `${previewFrameUrl}/${baseViewUrl}`;
|
||||||
// data.previewFrameUrl = `/${baseViewUrl}`;
|
|
||||||
data.shareUrl = shareUrl;
|
data.shareUrl = shareUrl;
|
||||||
|
|
||||||
if (req.headers.referer) {
|
// TODO: Need to review this logic, conflicts with the browsersync work after "/sync" action.
|
||||||
// NGROK, public URL
|
// if (req.headers.referer) {
|
||||||
data.shareUrl = undefined; // Link already shared.
|
// // NGROK, public URL
|
||||||
data.previewFrameUrl = `/${baseViewUrl}`;
|
// data.shareUrl = undefined; // Link already shared.
|
||||||
data.publicUrl = true;
|
// data.previewFrameUrl = `/${baseViewUrl}`;
|
||||||
}
|
// data.publicUrl = true;
|
||||||
|
// }
|
||||||
|
|
||||||
res.render('index', data);
|
res.render('index', data);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/view/:baseView', (req, res) => {
|
app.get('/view/:baseView', (req, res) => {
|
||||||
const data = {config: getBlockConfigs({modulesPath, dataFiles})};
|
const data = getDataOfFrame(!!req.query.iframe);
|
||||||
|
|
||||||
if (data.error && data.errorMessage) {
|
if (data.error && data.errorMessage) {
|
||||||
return res.send(data.errorMessage);
|
return res.send(data.errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.helpers = {
|
const baseView = req.params.baseView ?? DEFAULT_VIEW_LAYOUT;
|
||||||
include_partial: (filesPath) => handlebarLayoutsPath(modulesPath, filesPath),
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!req.query.iframe) {
|
|
||||||
data.iframeMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseView = req.params.baseView ?? 'container';
|
|
||||||
|
|
||||||
res.render(baseView, data)
|
res.render(baseView, data)
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/publish', async (req, res) => {
|
app.get('/publish', async (req, res) => {
|
||||||
const data = await readJSONFile(path.join(projectPath, `block.json`));
|
const data = await readJSONFile(path.join(projectPath, `block.json`));
|
||||||
|
|
||||||
|
// Trigger build on the registry server only if the type of the unit is `foundation` or `component`.
|
||||||
|
const uploadStaticFiles = ['foundation', 'component'].includes(data.type);
|
||||||
|
|
||||||
|
// Prepare list of static files for the registry server.
|
||||||
|
if (uploadStaticFiles) {
|
||||||
|
data.static_files = {
|
||||||
|
css: getBlockName(data.name).name + '.min.css',
|
||||||
|
js: getBlockName(data.name).name + '.min.js',
|
||||||
|
images: await getImagesList(path.join(projectPath, 'src', 'images')),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await isFileEmpty(path.join(projectPath, `src/scripts`, data.static_files.js), true)) {
|
||||||
|
delete data.static_files.js;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.static_files.images.length) {
|
||||||
|
delete data.static_files.images;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let responseData = {
|
let responseData = {
|
||||||
uploadUrl: undefined
|
uploadBundleUrl: undefined,
|
||||||
|
staticFilesUrls: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -149,35 +201,87 @@ app.get('/publish', async (req, res) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseData.uploadUrl) {
|
// Start files uploading process.
|
||||||
await zipProject(path.join(projectPath, 'src'), path.join(projectPath, 'dist.zip'));
|
try {
|
||||||
const body = await fs.readFile(path.join(projectPath, 'dist.zip'));
|
if (responseData.uploadBundleUrl) {
|
||||||
const response = await fetch(`${responseData.uploadUrl}`, {
|
await zipProject(path.join(projectPath, 'src'), path.join(projectPath, 'dist.zip'));
|
||||||
method: 'PUT',
|
await uploadFile(path.join(projectPath, 'dist.zip'), responseData.uploadBundleUrl); // Bundle
|
||||||
body,
|
}
|
||||||
headers: {'Content-Type': 'application/zip'}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.status !== 200) {
|
if (uploadStaticFiles) {
|
||||||
res.json({success: false, message: "Can't upload the archive, permissions error."});
|
if (responseData.staticFilesUrls.css) {
|
||||||
// TODO: Need to update the registry server.
|
await uploadFile(
|
||||||
await fs.unlink(path.join(projectPath, 'dist.zip'));
|
path.join(projectPath, 'src/styles', data.static_files.css),
|
||||||
|
responseData.staticFilesUrls.css.uploadUrl,
|
||||||
|
(content) => {
|
||||||
|
if (responseData.staticFilesUrls.images) {
|
||||||
|
content = replaceNames(content, data.static_files.images, responseData.staticFilesUrls.images);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCommentsFromCss(content)
|
||||||
|
return content;
|
||||||
|
}); // CSS
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseData.staticFilesUrls.js) {
|
||||||
|
await uploadFile(
|
||||||
|
path.join(projectPath, 'src/scripts', data.static_files.js),
|
||||||
|
responseData.staticFilesUrls.js.uploadUrl,
|
||||||
|
(data) => removeCommentsFromJs(data)
|
||||||
|
); // JS
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseData.staticFilesUrls.images) {
|
||||||
|
for (let i = 0; i < data.static_files.images.length; i++) {
|
||||||
|
await uploadFile(
|
||||||
|
path.join(projectPath, 'src/images', data.static_files.images[i]),
|
||||||
|
responseData.staticFilesUrls.images[i].uploadUrl,
|
||||||
|
); // Images
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// TODO: Need to update the registry server.
|
||||||
|
await fs.unlink(path.join(projectPath, 'dist.zip')); // Remove local bundle
|
||||||
|
|
||||||
|
res.json({success: false, message: err.message});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.unlink(path.join(projectPath, 'dist.zip')); // Remove local bundle
|
||||||
|
|
||||||
|
// Trigger project's global files build on the registry server.
|
||||||
|
if (uploadStaticFiles) {
|
||||||
|
try {
|
||||||
|
await triggerGlobalProjectFilesBuild(getBlockName(data.name).project);
|
||||||
|
} catch (err) {
|
||||||
|
res.json({success: false, message: 'Something wrong with Project Builder.'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await syncFilesWithCloud(path.join(projectPath, 'block.json'), bs);
|
||||||
|
} catch (err) {
|
||||||
|
res.json({success: false, message: err});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
res.json({success: true});
|
res.json({success: true});
|
||||||
|
|
||||||
await fs.unlink(path.join(projectPath, 'dist.zip'));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/data', async (req, res) => {
|
app.get('/data', async (req, res) => {
|
||||||
let jsonDataFileName = req.query.name ? req.query.name : 'default';
|
let jsonDataFileName = req.query.name ? req.query.name : 'default';
|
||||||
|
|
||||||
const dataFiles = prepareListOfDataFiles(await fs.readdir(path.join(projectPath, 'data')));
|
const dataFiles = await getDataFiles(projectPath);
|
||||||
const data = await getBlockData(jsonDataFileName, {projectPath});
|
const data = await getBlockData(jsonDataFileName, {projectPath});
|
||||||
const designPreviewFiles = getListOfDesignPreviewFiles(jsonDataFileName, await fs.readdir(path.join(projectPath, 'design', 'preview')));
|
|
||||||
|
let designPreviewFiles = [];
|
||||||
|
try {
|
||||||
|
designPreviewFiles = getListOfDesignPreviewFiles(jsonDataFileName, await fs.readdir(path.join(projectPath, 'design', 'preview')));
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Preview Design doesn\'t exist');
|
||||||
|
}
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
dataOptions: dataFiles,
|
dataOptions: dataFiles,
|
||||||
@@ -186,6 +290,22 @@ app.get('/data', async (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.post('/sync', async (req, res) => {
|
||||||
|
if (req.body['ignore']) {
|
||||||
|
ignoreVersionSync = true;
|
||||||
|
res.json({status: 200, message: 'Version upgrade is ignored.'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await syncFilesWithCloud(path.join(projectPath, `block.json`), bs, true);
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).json({status: 500, message: err});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({status: 200, message: 'Successfully synced!'});
|
||||||
|
});
|
||||||
|
|
||||||
// Errors handler
|
// Errors handler
|
||||||
app.use(handleSyntaxErrors);
|
app.use(handleSyntaxErrors);
|
||||||
|
|
||||||
@@ -230,6 +350,23 @@ function getListOfDesignPreviewFiles(jsonDataFileName, previewFiles) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDataOfFrame(isIframe = false) {
|
||||||
|
const data = {config: getBlockConfigs({modulesPath, dataFiles})};
|
||||||
|
if (data.error && data.errorMessage) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.helpers = {
|
||||||
|
include_partial: (filesPath) => handlebarLayoutsPath(modulesPath, filesPath),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isIframe) {
|
||||||
|
data.iframeMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
function startBrowserSync() {
|
function startBrowserSync() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const listener = httpServer.listen(0, async () => {
|
const listener = httpServer.listen(0, async () => {
|
||||||
@@ -237,7 +374,8 @@ function startBrowserSync() {
|
|||||||
|
|
||||||
console.log(`The web server has started on port ${PORT}`);
|
console.log(`The web server has started on port ${PORT}`);
|
||||||
|
|
||||||
const bs = browserSync.create();
|
// BS is global variable.
|
||||||
|
bs = browserSync.create();
|
||||||
|
|
||||||
const files = getJSBundleFiles();
|
const files = getJSBundleFiles();
|
||||||
gulp.watch(files, {delay: 400}, gulp.series(['build-script-files', function (cb) {
|
gulp.watch(files, {delay: 400}, gulp.series(['build-script-files', function (cb) {
|
||||||
@@ -431,11 +569,36 @@ async function getShareableUrl() {
|
|||||||
|
|
||||||
let url;
|
let url;
|
||||||
try {
|
try {
|
||||||
await authtoken(data.ngrokApiToken);
|
// await authtoken(data.ngrokApiToken);
|
||||||
url = await connect(port);
|
// url = await connect(port);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Error:', `Can't connect to ngrok, probably wrong token.`);
|
console.log('Error:', `Can't connect to ngrok, probably wrong token.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function triggerGlobalProjectFilesBuild(project) {
|
||||||
|
const response = await fetch(`${blocksRegistry}/project-files`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({project}),
|
||||||
|
headers: {'Content-Type': 'application/json'}
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataFiles(projectPath) {
|
||||||
|
const dataFiles = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.access(path.join(projectPath, 'data'));
|
||||||
|
|
||||||
|
const files = prepareListOfDataFiles(await fs.readdir(path.join(projectPath, 'data')));
|
||||||
|
dataFiles.push(...files);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Warning: data folder not found.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataFiles;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user