Added support of Project Global Assets.
This commit is contained in:
+76
-1
@@ -9,6 +9,8 @@ import archiver from "archiver";
|
||||
import {buildWordPress} from "./platforms/wordpress/wordpress-adapter.js";
|
||||
import {buildHubspotEmail} from "./platforms/hubspot/hubspot-email-adapter.js";
|
||||
import {buildHubspotPage} from "./platforms/hubspot/hubspot-page-adapter.js";
|
||||
import fs from "fs/promises";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@@ -53,7 +55,7 @@ export async function getBlockData(jsonFileName = 'default', {projectPath} = {js
|
||||
}
|
||||
|
||||
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) => {
|
||||
return {
|
||||
@@ -61,6 +63,14 @@ export function getBlockConfigs(args = {modulesPath: '', dataFiles: []}) {
|
||||
};
|
||||
}), 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 = '') {
|
||||
@@ -160,3 +170,68 @@ export async function buildExportFiles(blockName, platform) {
|
||||
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) {
|
||||
let body = await fs.readFile(filePath, {encoding: 'utf8'});
|
||||
|
||||
if (validator) {
|
||||
body = validator(body);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(uploadUrl, {
|
||||
method: 'PUT',
|
||||
body: body,
|
||||
headers: {'Content-Type': 'application/javascript'}
|
||||
});
|
||||
|
||||
return response.status !== 200;
|
||||
} catch (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);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<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"/>
|
||||
{{#if config.project.css }} <link rel="stylesheet" href="{{ config.project.css }}">
|
||||
{{/if}}
|
||||
{{#if config.cssUrl }}
|
||||
{{#each config.cssUrl }}
|
||||
<link rel="stylesheet" href="{{ this }}">
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.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://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}}
|
||||
{{/if}}
|
||||
|
||||
+3
-3
@@ -7,9 +7,9 @@
|
||||
"url": "https://axe-web.com/"
|
||||
},
|
||||
"scripts": {
|
||||
"info": "NODE_ENV=development BLOCK_NAME=comparison-table MODULE_PATH= node debug.js",
|
||||
"dev": "NODE_ENV=development BLOCK_NAME=comparison-table MODULE_PATH= node server.js",
|
||||
"build-platform": "NODE_ENV=development BLOCK_NAME=comparison-table MODULE_PATH= node ./build.js",
|
||||
"info": "NODE_ENV=development BLOCK_NAME=content MODULE_PATH= node debug.js",
|
||||
"dev": "NODE_ENV=development BLOCK_NAME=content MODULE_PATH= node server.js",
|
||||
"build-platform": "NODE_ENV=development BLOCK_NAME=content MODULE_PATH= node ./build.js",
|
||||
"dev-dev-tool": "NODE_ENV=development rollup --config rollup.config.js --watch",
|
||||
"build-dev-tool": "rollup --config rollup.config.js"
|
||||
},
|
||||
|
||||
@@ -19,7 +19,19 @@ import open from "open";
|
||||
import {sanitizeUrl} from "@braintree/sanitize-url";
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import {escape} from "lodash-es";
|
||||
import {getBlockData, getBlockConfigs, getConfigs, readJSONFile, zipProject} from "./helpers.js";
|
||||
import {
|
||||
getBlockConfigs,
|
||||
getBlockData,
|
||||
getBlockName,
|
||||
getConfigs,
|
||||
getImagesList,
|
||||
isFileEmpty,
|
||||
readJSONFile,
|
||||
removeCommentsFromCss,
|
||||
removeCommentsFromJs,
|
||||
uploadFile,
|
||||
zipProject
|
||||
} from "./helpers.js";
|
||||
import PluginError from 'plugin-error';
|
||||
import {Server} from "socket.io";
|
||||
import {createServer} from 'http';
|
||||
@@ -93,7 +105,6 @@ app.get('/', (req, res) => {
|
||||
data.baseView = baseView;
|
||||
data.port = `/${baseViewUrl}`;
|
||||
data.previewFrameUrl = `${previewFrameUrl}/${baseViewUrl}`;
|
||||
// data.previewFrameUrl = `/${baseViewUrl}`;
|
||||
data.shareUrl = shareUrl;
|
||||
|
||||
if (req.headers.referer) {
|
||||
@@ -127,8 +138,24 @@ app.get('/view/:baseView', (req, res) => {
|
||||
|
||||
app.get('/publish', async (req, res) => {
|
||||
const data = await readJSONFile(path.join(projectPath, `block.json`));
|
||||
|
||||
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 = {
|
||||
uploadUrl: undefined
|
||||
uploadBundleUrl: undefined,
|
||||
staticFilesUrls: {}
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -149,27 +176,53 @@ app.get('/publish', async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (responseData.uploadUrl) {
|
||||
await zipProject(path.join(projectPath, 'src'), path.join(projectPath, 'dist.zip'));
|
||||
const body = await fs.readFile(path.join(projectPath, 'dist.zip'));
|
||||
const response = await fetch(`${responseData.uploadUrl}`, {
|
||||
method: 'PUT',
|
||||
body,
|
||||
headers: {'Content-Type': 'application/zip'}
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
res.json({success: false, message: "Can't upload the archive, permissions error."});
|
||||
// TODO: Need to update the registry server.
|
||||
await fs.unlink(path.join(projectPath, 'dist.zip'));
|
||||
return;
|
||||
// Start files uploading process.
|
||||
try {
|
||||
if (responseData.uploadBundleUrl) {
|
||||
await zipProject(path.join(projectPath, 'src'), path.join(projectPath, 'dist.zip'));
|
||||
await uploadFile(path.join(projectPath, 'dist.zip'), responseData.uploadBundleUrl); // Bundle
|
||||
}
|
||||
|
||||
// TODO: Upload CSS/JS/Images files only if the type of the unit is `foundation` or `component`.
|
||||
if (responseData.staticFilesUrls.css) {
|
||||
await uploadFile(
|
||||
path.join(projectPath, 'src/styles', data.static_files.css),
|
||||
responseData.staticFilesUrls.css.uploadUrl,
|
||||
(data) => removeCommentsFromCss(data)); // 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
|
||||
|
||||
// TODO: Trigger build on the registry server only if the type of the unit is `foundation` or `component`.
|
||||
try {
|
||||
await triggerGlobalProjectFilesBuild(getBlockName(data.name).project);
|
||||
} catch (err) {
|
||||
res.json({success: false, message: 'Something wrong with Project Builder.'});
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({success: true});
|
||||
|
||||
await fs.unlink(path.join(projectPath, 'dist.zip'));
|
||||
});
|
||||
|
||||
app.get('/data', async (req, res) => {
|
||||
@@ -177,7 +230,13 @@ app.get('/data', async (req, res) => {
|
||||
|
||||
const dataFiles = prepareListOfDataFiles(await fs.readdir(path.join(projectPath, 'data')));
|
||||
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({
|
||||
dataOptions: dataFiles,
|
||||
@@ -439,3 +498,13 @@ async function getShareableUrl() {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user