Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4192d16b7a | ||
|
|
12abd35cfa | ||
|
|
073ed52932 | ||
|
|
8f2605be9d | ||
|
|
9e7860542b | ||
|
|
f48b2a3274 |
No files matched your search
+19
@@ -0,0 +1,19 @@
|
|||||||
|
FROM node:19.4.0-slim as node
|
||||||
|
|
||||||
|
WORKDIR /app/
|
||||||
|
|
||||||
|
COPY ./package.json .
|
||||||
|
COPY ./package-lock.json .
|
||||||
|
COPY ./inc ./inc
|
||||||
|
COPY ./layouts ./layouts
|
||||||
|
COPY ./platforms ./platforms
|
||||||
|
COPY ./routes ./routes
|
||||||
|
COPY ./env.js .
|
||||||
|
COPY ./helpers.js .
|
||||||
|
COPY ./rollup.config.js .
|
||||||
|
COPY ./server.js .
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
EXPOSE 3010
|
||||||
|
CMD npm run view-mode
|
||||||
@@ -9,8 +9,17 @@ 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'
|
||||||
|
|||||||
+120
-49
@@ -14,6 +14,7 @@ import {constants} from "fs";
|
|||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import mime from "mime-types";
|
import mime from "mime-types";
|
||||||
import {exec} from "child_process";
|
import {exec} from "child_process";
|
||||||
|
import {REGISTRY_URL} from "@axe-web/create-block/env.js";
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
@@ -61,14 +62,16 @@ export async function getBlockData(jsonFileName = 'default', {projectPath} = {js
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBlockConfigs(args = {modulesPath: '', dataFiles: []}) {
|
export async function getBlockConfigs(args) {
|
||||||
const updatedConfig = Object.assign(JSON.parse(JSON.stringify(config)), // The entire config object.
|
const config = await readJSONFile(path.join('blocks', '@' + args.project, args.name, 'config', 'default.json'));
|
||||||
|
|
||||||
|
const updatedConfig = Object.assign({}, config, // The entire config object.
|
||||||
{
|
{
|
||||||
projectDir: args.modulesPath, dataFiles: args.dataFiles.map((name) => {
|
projectDir: '', dataFiles: args.dataFiles.map((name) => {
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
};
|
};
|
||||||
}), remToPx: config.has('remToPx') ? config.get('remToPx') : 16,
|
}), remToPx: 16,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Avoid cache conflict on Global Project css/js files.
|
// Avoid cache conflict on Global Project css/js files.
|
||||||
@@ -81,13 +84,13 @@ export function getBlockConfigs(args = {modulesPath: '', dataFiles: []}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getBlockName(name = '') {
|
export function getBlockName(name = '') {
|
||||||
if (name.startsWith('@')) {
|
// Remove all @ from the beginning of the string.
|
||||||
name = name.substring(1);
|
name = name.replace(/^@/, '');
|
||||||
}
|
|
||||||
|
|
||||||
const arr = name.split('/');
|
const arr = name.split('/');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
blockName: `@${arr[0]}/${arr[1]}`,
|
||||||
project: arr[0],
|
project: arr[0],
|
||||||
name: arr[1],
|
name: arr[1],
|
||||||
};
|
};
|
||||||
@@ -126,33 +129,46 @@ 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', {});
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
// listen for all archive data to be written
|
||||||
// Create a file to write the archive data
|
// 'close' event is fired only when a file descriptor is involved
|
||||||
const archive = archiver('zip', {
|
output.on('close', function () {
|
||||||
zlib: {level: 9} // Compression level
|
console.log(archive.pointer() + ' total bytes');
|
||||||
});
|
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) {
|
||||||
@@ -262,7 +278,7 @@ export async function getBlockFromCloud(blockName, blocksRegistry) {
|
|||||||
const response = await fetch(`${blocksRegistry}?${queryString.toString()}`);
|
const response = await fetch(`${blocksRegistry}?${queryString.toString()}`);
|
||||||
const responseData = await response.json();
|
const responseData = await response.json();
|
||||||
if (!responseData || !responseData.name) {
|
if (!responseData || !responseData.name) {
|
||||||
const message = "⚠️ Block not found, please contact administrator."
|
const message = `⚠️ Block not found, please contact administrator. [${blockName}]`
|
||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,12 +290,15 @@ export async function getBlockFromCloud(blockName, blocksRegistry) {
|
|||||||
return responseData;
|
return responseData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function verifyVersion(projectPath, blocksRegistry) {
|
export async function verifyVersion(blockName, projectPath, blocksRegistry) {
|
||||||
const blockJson = await readJSONFile(path.join(projectPath, `block.json`));
|
const block = await getBlockFromCloud(blockName, blocksRegistry);
|
||||||
const blockName = getBlockName(blockJson.name);
|
if (!block) {
|
||||||
|
throw new Error(`Block not found. [${blockName}]`);
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof blockJson.version === 'undefined' || !blockName.name) {
|
const blockJson = await readJSONFile(path.join(projectPath, `block.json`));
|
||||||
return true;
|
if (blockJson.error) {
|
||||||
|
return false; // Block doesn't exist locally.
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -287,25 +306,28 @@ export async function verifyVersion(projectPath, blocksRegistry) {
|
|||||||
* Let's detect the latest version.
|
* Let's detect the latest version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const block = await getBlockFromCloud('@' + blockJson.name, blocksRegistry);
|
|
||||||
return block.version === blockJson.version;
|
return block.version === blockJson.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function syncFilesWithCloud(jsonBlockPath, bs, sourceFiles = false) {
|
export async function syncFilesWithCloud(blockName, bs, sourceFiles = false) {
|
||||||
const blockJson = await readJSONFile(jsonBlockPath);
|
const block = await getBlockFromCloud(blockName, REGISTRY_URL);
|
||||||
const blockName = blockJson.name.startsWith('@') ? blockJson.name : `@${blockJson.name}`;
|
|
||||||
|
|
||||||
bs.pause();
|
let fileExists = false;
|
||||||
|
try {
|
||||||
|
await readJSONFile(path.join('blocks', '@' + block.project, block.name, 'block.json'));
|
||||||
|
fileExists = true;
|
||||||
|
} catch (e) {
|
||||||
|
// Dir doesn't exist.
|
||||||
|
}
|
||||||
|
|
||||||
// Looks like it takes time to pause the browser-sync server, so delay(setTimeout) is necessary.
|
// TODO: Pause watcher of the block?
|
||||||
await new Promise((resolve) => setTimeout(() => resolve(), 1000));
|
blockName = `@${block.project}/${block.name}`;
|
||||||
|
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
const args = sourceFiles ? '--source' : '';
|
|
||||||
const createBlockModulePath = `./node_modules/@axe-web/create-block`;
|
const createBlockModulePath = `./node_modules/@axe-web/create-block`;
|
||||||
|
const action = sourceFiles ? fileExists ? 'sync --source' : 'pull' : 'sync';
|
||||||
|
|
||||||
// exec(`BLOCK_NAME=${blockName} node ${createBlockModulePath}/create-block.js sync ${args}`, (err, stdout, stderr) => {
|
exec(`BLOCK_NAME=${blockName} node ${createBlockModulePath}/create-block.js ${action}`, (err, stdout, stderr) => {
|
||||||
exec(`node ${createBlockModulePath}/create-block.js sync ${args}`, (err, stdout, stderr) => {
|
|
||||||
if (err || stderr) {
|
if (err || stderr) {
|
||||||
const message = err || stderr;
|
const message = err || stderr;
|
||||||
console.error('Error:', message);
|
console.error('Error:', message);
|
||||||
@@ -317,5 +339,54 @@ export async function syncFilesWithCloud(jsonBlockPath, bs, sourceFiles = false)
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
bs.resume();
|
// TODO: Release watcher of the block?
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getBlockVariations(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.', projectPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function prepareListOfDataFiles(dataFiles) {
|
||||||
|
return dataFiles
|
||||||
|
.filter((fileName) => fileName.split('.').pop() === 'json')
|
||||||
|
.map((fileName) => {
|
||||||
|
const splitName = fileName.split('.');
|
||||||
|
splitName.pop();
|
||||||
|
return splitName.join('');
|
||||||
|
})
|
||||||
|
.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handlebarLayoutsPath() {
|
||||||
|
return path.join(...arguments)
|
||||||
|
.replace(/\\/g, '/'); // Windows path issue. Fix all "\" for Handlebars.
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getListOfDesignPreviewFiles(jsonDataFileName, previewFiles, block) {
|
||||||
|
return previewFiles
|
||||||
|
.filter(fileName => {
|
||||||
|
return fileName.startsWith(jsonDataFileName + '.');
|
||||||
|
})
|
||||||
|
.map(fileName => {
|
||||||
|
const fileData = fileName.split('.');
|
||||||
|
const fileFormat = fileData.pop();
|
||||||
|
const previewSize = fileData.pop();
|
||||||
|
|
||||||
|
return {
|
||||||
|
dataSource: jsonDataFileName,
|
||||||
|
widthDimension: Number.parseInt(previewSize, 10),
|
||||||
|
url: `/design/${block.project}/${block.name}/preview/${fileName}`,
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
import gulp from "gulp";
|
||||||
|
import path from "path";
|
||||||
|
import sourcemaps from "gulp-sourcemaps";
|
||||||
|
import babel from "gulp-babel";
|
||||||
|
import PluginError from "plugin-error";
|
||||||
|
import rename from "gulp-rename";
|
||||||
|
import uglify from "gulp-uglify";
|
||||||
|
import dartSass from 'sass';
|
||||||
|
import gulpSass from "gulp-sass";
|
||||||
|
import {getBlockName} from "../helpers.js";
|
||||||
|
|
||||||
|
const sass = gulpSass(dartSass);
|
||||||
|
|
||||||
|
export function setupWatcher(viewSync) {
|
||||||
|
|
||||||
|
const watchSCSS = gulp.watch(['blocks/**/*.scss'], {delay: 400});
|
||||||
|
watchSCSS.on('change', async function (filepath, stats) {
|
||||||
|
const pathArray = filepath.split('/', 3);
|
||||||
|
pathArray.shift();
|
||||||
|
const block = getBlockName(pathArray.join('/'));
|
||||||
|
|
||||||
|
buildStyleFiles(path.join('blocks', '@' + block.project, block.name), () => {
|
||||||
|
viewSync.syncTemplate(block.blockName, 'styleUpdate');
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const watchJS = gulp.watch(['blocks/**/*.js', '!blocks/**/*.min.js'], {delay: 400});
|
||||||
|
watchJS.on('change', async function (filepath) {
|
||||||
|
const pathArray = filepath.split('/', 3);
|
||||||
|
pathArray.shift();
|
||||||
|
const block = getBlockName(pathArray.join('/'));
|
||||||
|
|
||||||
|
buildScriptFiles(path.join('blocks', '@' + block.project, block.name), () => {
|
||||||
|
viewSync.syncTemplate(block.blockName, 'scriptUpdate');
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const watchHBS = gulp.watch(['blocks/**/*.hbs'], {delay: 400});
|
||||||
|
watchHBS.on('change', async function (filepath) {
|
||||||
|
const pathArray = filepath.split('/', 3);
|
||||||
|
pathArray.shift();
|
||||||
|
const block = getBlockName(pathArray.join('/'));
|
||||||
|
|
||||||
|
await viewSync.syncTemplate(block.blockName);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildAssetFiles(projectPath) {
|
||||||
|
// Register tasks.
|
||||||
|
gulp.task('build-script-files', (done) => buildScriptFiles(projectPath, done));
|
||||||
|
gulp.task('build-styling-files', (done) => buildStyleFiles(projectPath, done));
|
||||||
|
|
||||||
|
// Run first build.
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
gulp.series('build-script-files', 'build-styling-files', function () {
|
||||||
|
resolve();
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showError(errorMessage) {
|
||||||
|
console.log(errorMessage);
|
||||||
|
|
||||||
|
// TODO: Send this message to browser.
|
||||||
|
// So the developer can understand there is an error.
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildScriptFiles(projectPath = '', done) {
|
||||||
|
const files = getJSBundleFiles(projectPath);
|
||||||
|
const stream = gulp.src(files, {base: path.posix.join(projectPath, 'src')})
|
||||||
|
.pipe(sourcemaps.init({}))
|
||||||
|
.pipe(babel()).on('error', function (error) {
|
||||||
|
showError(new PluginError('JavaScript', error).toString());
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.pipe(gulp.src(path.join(projectPath, 'vendor/*.js')))
|
||||||
|
// .pipe(gulp.dest('src/'))
|
||||||
|
.pipe(rename({extname: '.min.js'}))
|
||||||
|
.pipe(uglify())
|
||||||
|
.pipe(sourcemaps.write('.'))
|
||||||
|
.pipe(gulp.dest(path.posix.join(projectPath, 'src')));
|
||||||
|
|
||||||
|
stream.on('end', done);
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getJSBundleFiles(projectPath = '') {
|
||||||
|
return [path.posix.join(projectPath, "src/**/*.js"), path.posix.join(projectPath, "src/**/*.mjs"), "!" + path.posix.join(projectPath, "src/**/*.min.js")];
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildStyleFiles(projectPath = '', done) {
|
||||||
|
const stream = gulp.src(path.join(projectPath, 'src/**/*.scss'), {base: path.posix.join(projectPath, 'src')})
|
||||||
|
.pipe(sourcemaps.init({}))
|
||||||
|
.pipe(sass.sync({outputStyle: 'compressed'}).on('error', function (error) {
|
||||||
|
showError(new PluginError('SCSS', error.messageFormatted).toString());
|
||||||
|
// sass.logError(error);
|
||||||
|
done();
|
||||||
|
}))
|
||||||
|
// .pipe(gulp.dest('src/'))
|
||||||
|
.pipe(rename({extname: '.min.css'}))
|
||||||
|
.pipe(sourcemaps.write('.', {}))
|
||||||
|
.pipe(gulp.dest(path.posix.join(projectPath, 'src')));
|
||||||
|
|
||||||
|
stream.on('end', done);
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export function setHeaders(req, res, next) {
|
||||||
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
next();
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import express from "express";
|
||||||
|
import bodyParser from "body-parser";
|
||||||
|
import {createServer} from "http";
|
||||||
|
import {create} from "express-handlebars";
|
||||||
|
import {escape} from "lodash-es";
|
||||||
|
import {sanitizeUrl} from "@braintree/sanitize-url";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export function init() {
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
// parse application/x-www-form-urlencoded
|
||||||
|
app.use(bodyParser.urlencoded({extended: false}));
|
||||||
|
|
||||||
|
// parse application/json
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
|
const hbs = getHandlebarsViewEngine();
|
||||||
|
|
||||||
|
app.engine('.hbs', hbs.engine);
|
||||||
|
app.set('view engine', '.hbs');
|
||||||
|
|
||||||
|
const modulesPath = '.';
|
||||||
|
app.set('views', path.join(modulesPath, 'layouts'));
|
||||||
|
|
||||||
|
// Static Files of blockDevTool.
|
||||||
|
app.use(express.static(path.join(modulesPath, 'layouts')));
|
||||||
|
|
||||||
|
return {
|
||||||
|
expressApp: app,
|
||||||
|
httpServer: createServer(app),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHandlebarsViewEngine() {
|
||||||
|
return create({
|
||||||
|
extname: '.hbs', defaultLayout: false, partialsDir: ['.'], helpers: handlebarsHelpers()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlebarsHelpers() {
|
||||||
|
return {
|
||||||
|
esc_attr(attr) {
|
||||||
|
return escape(attr);
|
||||||
|
},
|
||||||
|
esc_url(url) {
|
||||||
|
return sanitizeUrl(url);
|
||||||
|
},
|
||||||
|
esc_html(html) {
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import {Server} from "socket.io";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
import {getBlockName, handlebarLayoutsPath} from "../helpers.js";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export class ViewSync {
|
||||||
|
constructor(httpServer) {
|
||||||
|
this.sessions = {};
|
||||||
|
this.init(httpServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
addSession(session, blockName) {
|
||||||
|
if (!this.sessions[blockName]) {
|
||||||
|
this.sessions[blockName] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sessions[blockName].push(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
init(httpServer) {
|
||||||
|
const io = new Server(httpServer);
|
||||||
|
io.on('connection', async (socket) => {
|
||||||
|
const blockName = socket.handshake.query.block;
|
||||||
|
|
||||||
|
if (!blockName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addSession(socket, blockName);
|
||||||
|
await this.syncTemplate(blockName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// return httpServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
async syncTemplate(blockName, updateType = 'templateUpdate') {
|
||||||
|
const block = getBlockName(blockName);
|
||||||
|
|
||||||
|
const projectPath = path.join('blocks', '@' + block.project, block.name);
|
||||||
|
const hbsTemplate = await fs.readFile(handlebarLayoutsPath(projectPath, 'src', `${block.name}.template.hbs`), 'utf8');
|
||||||
|
|
||||||
|
if (!this.sessions[blockName]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sessions[blockName].forEach(session => {
|
||||||
|
session.emit(updateType, {block: blockName, template: hbsTemplate});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
{{> (include_partial "layouts/partials/head") }}
|
{{> (include_partial "layouts/partials/head") }}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
{{> (include_partial "layouts/partials/head") }}
|
{{> (include_partial "layouts/partials/head") }}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
{{> (include_partial "layouts/partials/head") }}
|
{{> (include_partial "layouts/partials/head") }}
|
||||||
|
|||||||
+4
-2
@@ -1,3 +1,4 @@
|
|||||||
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
@@ -7,12 +8,13 @@
|
|||||||
<title>Block Development Tool</title>
|
<title>Block Development Tool</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body class="{{#if viewMode }}view-mode{{/if}}">
|
||||||
|
|
||||||
{{> (include_partial "layouts/partials/toolbar") }}
|
{{> (include_partial "layouts/partials/toolbar") }}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.devTool = {
|
window.devTool = {
|
||||||
|
blockName: '{{ blockName }}',
|
||||||
previewFrameUrl: '{{ previewFrameUrl }}',
|
previewFrameUrl: '{{ previewFrameUrl }}',
|
||||||
{{#if publicUrl}}
|
{{#if publicUrl}}
|
||||||
publicUrl: true,
|
publicUrl: true,
|
||||||
@@ -21,7 +23,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
<iframe id="preview_frame" src="{{ previewFrameUrl }}?iframe=true" class="breakpoint"></iframe>
|
<iframe id="preview_frame" src="{{ previewFrameUrl }}?iframe=true&block={{blockName}}" class="breakpoint"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/scripts/dist/index.min.js"></script>
|
<script src="/scripts/dist/index.min.js"></script>
|
||||||
|
|||||||
@@ -10,5 +10,5 @@
|
|||||||
<link rel="stylesheet" href="{{ this }}">
|
<link rel="stylesheet" href="{{ this }}">
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}<link rel="stylesheet" href="/styles/page--view.css">{{# if config.blockName}}
|
{{/if}}<link rel="stylesheet" href="/styles/page--view.css">{{# if config.blockName}}
|
||||||
<link rel="stylesheet" href="/styles/{{ config.blockName }}.min.css">{{/if}}
|
<link rel="stylesheet" id="block-stylesheet" href="{{staticFilesPath}}/styles/{{ config.blockName }}.min.css?v=1">{{/if}}
|
||||||
</head>
|
</head>
|
||||||
@@ -10,5 +10,5 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if config.blockName }}
|
{{#if config.blockName }}
|
||||||
<script src="/scripts/{{ config.blockName }}.min.js"></script>
|
<script id="block-script" src="{{staticFilesPath}}/scripts/{{ config.blockName }}.min.js?v=1"></script>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -15,6 +15,6 @@
|
|||||||
{{#if styleGuideUrl}}
|
{{#if styleGuideUrl}}
|
||||||
<a href="{{ styleGuideUrl }}" target="_blank" class="palette" title="Open Style Guide"></a>
|
<a href="{{ styleGuideUrl }}" target="_blank" class="palette" title="Open Style Guide"></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<a href="{{ previewFrameUrl }}" target="_blank" class="open_in_new_tab" title="Open in New Window"></a>
|
<a href="{{ previewFrameUrl }}?block={{blockName}}" target="_blank" class="open_in_new_tab" title="Open in New Window"></a>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
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 e;window.initBlock=function(e="",n="",o){t=function(){document.querySelectorAll(n).forEach((e=>o(e)))},t()};let t,n={};!function(){const o=r().block;function r(){const e=new URLSearchParams(window.location.search),t={};for(const[n,o]of e)t[n]=o;return t}function a(e){const t=document.getElementById(e),n=t.parentNode;let o,r;return"SCRIPT"===t.tagName?(o=document.createElement("script"),o.type="text/javascript",r="src"):"LINK"===t.tagName&&(o=document.createElement("link"),o.rel="stylesheet",r="href"),o.id=e,o[r]=t[r].replace(/(\?v=)[^&]+/,`$1${Date.now()}`),t.remove(),n.append(o),o}function c(r={}){r.template&&(e=r.template),r.data&&(n=r.data),e&&function(e,n,r){const a=Handlebars.compile(e);let c;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(){const e=["block"];return o&&e.push(o.substr(1)),["",...e,""].join("/")}));try{c=a(n)}catch(e){c=`<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=c,t&&t()}(e,n||{},document.getElementById("hbs-container"))}!function(){const e=new URLSearchParams({block:o,name:r().data||"default"});fetch(`/data?${e}`).then((e=>e.json())).then((e=>{n=e.data,c({data:n})}))}(),window.addEventListener("message",(function(e){const t=e.data,o="dataUpdate:";if("string"==typeof t&&t.startsWith(o))try{n=JSON.parse(t.substring(o.length)),c({data:n})}catch(e){console.log("Error parsing incoming data.",e)}})),function(){const e=window.io.connect("",{query:`block=${o}`});e.on("error",(function(e){console.log(e)})),e.on("templateUpdate",(function(e){c({template:e.template})})),e.on("scriptUpdate",(function(e){a("block-script").onload=()=>{c({template:e.template})}})),e.on("styleUpdate",(function(e){a("block-stylesheet")}))}()}();
|
||||||
Vendored
+1
-1
@@ -261,4 +261,4 @@ var U=t.exports,B=$.exports;function V(e){for(var t="https://reactjs.org/docs/er
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: top;
|
background-position: top;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
`;let zp={x:0,y:0};function Np({previewOption:e={widthDimension:0}}){const n=t.exports.createRef(),[r,a]=t.exports.useState(!1),[l,o]=t.exports.useState({x:m(e),y:0}),[i,u]=t.exports.useState(85),s=t.exports.useCallback((function(e){if(!r)return;const t=e.shiftKey?10:1;"ArrowUp"===e.key?p({y:-1*t},!0):"ArrowDown"===e.key?p({y:t},!0):"ArrowLeft"===e.key?p({x:-1*t},!0):"ArrowRight"===e.key&&p({x:t},!0)}),[l,r]);if(t.exports.useEffect((()=>(document.addEventListener("keydown",s),()=>{document.removeEventListener("keydown",s)})),[s]),t.exports.useEffect((()=>(p({x:m(e),y:0}),window.addEventListener("message",h),()=>window.removeEventListener("message",h))),[e.widthDimension]),!e)return;const c=!e.url,f=[];!c&&r&&f.push("active"),c&&f.push("disabled");return M.createElement(M.Fragment,null,M.createElement(_p,{onClick:()=>{a(!r)},className:f.join(" "),disabled:c}),r&&!c&&M.createElement(M.Fragment,null,M.createElement("input",{type:"range",value:i,min:"0",max:"100",onChange:e=>{u(e.target.value)}}),M.createElement(Pp,{onMouseUp:e=>function(e){const t=n.current;p({x:t.offsetLeft,y:t.offsetTop}),document.body.removeEventListener("mousemove",d)}(),style:{opacity:i/100}},M.createElement("img",{src:e.url,alt:"",ref:n,onMouseDown:e=>function(e){zp.x=e.clientX,zp.y=e.clientY,document.body.addEventListener("mousemove",d)}(e),draggable:!1,style:{top:l.y+"px",left:l.x+"px"}}))));function d(e){const t=n.current;if(t){const n={x:t.offsetLeft-(zp.x-e.clientX),y:t.offsetTop-(zp.y-e.clientY)};t.style.left=n.x+"px",t.style.top=n.y+"px",zp.x=e.clientX,zp.y=e.clientY}}function p({x:e,y:t},n=!1){e=void 0===e?l.x:n?l.x+e:e,t=void 0===t?l.y:n?l.y+t:t,o({x:e,y:t})}function m(e){if(!e)return 0;return window.innerWidth/2-e.widthDimension/2-7}function h(t){"responsiveUpdate"===t.data&&"100%"===window.responsiveState.breakpoint&&p({x:m(e),y:0})}}function Tp(e={}){e.rootAttributes=e.rootAttributes??{};const[n,r]=t.exports.useState({dataName:"default",data:{},dataText:"{}",dataOptions:[],designPreview:[],errorMessage:null,loading:!1}),[a,l]=t.exports.useState(f(n.dataName,n.designPreview)),o=e=>r(Object.assign({},n,e)),[i,u]=t.exports.useState(!1);t.exports.useEffect((async()=>{await p(n.dataName)}),[]);const s=t.exports.useCallback((e=>{vp(e)&&c()}),[]);t.exports.useEffect((()=>(document.addEventListener("keydown",s),()=>{document.removeEventListener("keydown",s)})),[s]),t.exports.useEffect((()=>(window.addEventListener("message",d),()=>window.removeEventListener("message",d))),[n]),t.exports.useEffect((()=>{l(f(n.dataName,n.designPreview))}),[n.designPreview]);return M.createElement("div",{style:{display:"flex",gap:"1rem",alignItems:"center"}},M.createElement(xp,{onClick:()=>(u(!0),void setTimeout((()=>document.querySelector(".sidebar-active").focus()))),title:"Open a Sidebar with Data Options"}),M.createElement(Np,{previewOption:a}),M.createElement(wp,{className:i?"active sidebar-active":"",tabIndex:"0",onBlur:async e=>await gp(e)?c():null},M.createElement(Sp,null,M.createElement(Cp,{onClick:()=>c()})),n.dataOptions&&!!n.dataOptions.length&&M.createElement(Ep,null,M.createElement("label",{htmlFor:"data-options"},"Data Options"),M.createElement("select",{name:"data",id:"data-options",onChange:e=>async function(e){const t=e.target.value;await p(t)}(e),value:n.dataName,disabled:n.loading},n.dataOptions.map((e=>{const t=n.dataName===e;return M.createElement("option",{value:e,selected:t},e)})))),n.data&&M.createElement("textarea",{value:n.dataText,onChange:function(e){let t;try{t=JSON.parse(e.target.value)}catch(t){return void o({dataText:e.target.value,errorMessage:"Invalid JSON, please review and try again."})}o({dataText:e.target.value,data:t,errorMessage:null}),m(t)},disabled:n.loading}),n.errorMessage&&M.createElement("p",{className:"alert alert--error"},n.errorMessage),n.loading&&M.createElement("p",{className:"alert"},"Loading, please wait..."),M.createElement("div",{className:"actions"},M.createElement("button",{className:"btn btn--secondary",disabled:n.loading,onClick:e=>function(e,t){e.stopPropagation(),"string"!=typeof t&&(t=JSON.stringify(t,null,2));if(navigator.clipboard&&window.isSecureContext)return navigator.clipboard.writeText(t);{let n=document.createElement("textarea");return n.value=t,n.style.position="fixed",n.style.left="-999999px",n.style.top="-999999px",document.body.appendChild(n),n.select(),new Promise(((t,r)=>{document.execCommand("copy")?t():r(),n.remove(),e.target.focus()}))}}(e,n.data)},"Copy to Clipboard"),M.createElement("button",{className:"btn btn--secondary",disabled:n.loading,onClick:e=>function(){const e="https://blocks-registery.axe-web.com/content-generator/",t=new Headers;t.append("Content-Type","application/json");const r={method:"POST",headers:t,body:JSON.stringify({json:n.data})};return o({loading:!0,errorMessage:null}),fetch(e,r).then((e=>e.json())).then((e=>{if(console.log(e),200!==e.statusCode)throw new Error(e.message);const t=e.variation;o({dataText:JSON.stringify(t,null,2),data:t,errorMessage:
Line truncated
|
`;let zp={x:0,y:0};function Np({previewOption:e={widthDimension:0}}){const n=t.exports.createRef(),[r,a]=t.exports.useState(!1),[l,o]=t.exports.useState({x:m(e),y:0}),[i,u]=t.exports.useState(85),s=t.exports.useCallback((function(e){if(!r)return;const t=e.shiftKey?10:1;"ArrowUp"===e.key?p({y:-1*t},!0):"ArrowDown"===e.key?p({y:t},!0):"ArrowLeft"===e.key?p({x:-1*t},!0):"ArrowRight"===e.key&&p({x:t},!0)}),[l,r]);if(t.exports.useEffect((()=>(document.addEventListener("keydown",s),()=>{document.removeEventListener("keydown",s)})),[s]),t.exports.useEffect((()=>(p({x:m(e),y:0}),window.addEventListener("message",h),()=>window.removeEventListener("message",h))),[e.widthDimension]),!e)return;const c=!e.url,f=[];!c&&r&&f.push("active"),c&&f.push("disabled");return M.createElement(M.Fragment,null,M.createElement(_p,{onClick:()=>{a(!r)},className:f.join(" "),disabled:c}),r&&!c&&M.createElement(M.Fragment,null,M.createElement("input",{type:"range",value:i,min:"0",max:"100",onChange:e=>{u(e.target.value)}}),M.createElement(Pp,{onMouseUp:e=>function(e){const t=n.current;p({x:t.offsetLeft,y:t.offsetTop}),document.body.removeEventListener("mousemove",d)}(),style:{opacity:i/100}},M.createElement("img",{src:e.url,alt:"",ref:n,onMouseDown:e=>function(e){zp.x=e.clientX,zp.y=e.clientY,document.body.addEventListener("mousemove",d)}(e),draggable:!1,style:{top:l.y+"px",left:l.x+"px"}}))));function d(e){const t=n.current;if(t){const n={x:t.offsetLeft-(zp.x-e.clientX),y:t.offsetTop-(zp.y-e.clientY)};t.style.left=n.x+"px",t.style.top=n.y+"px",zp.x=e.clientX,zp.y=e.clientY}}function p({x:e,y:t},n=!1){e=void 0===e?l.x:n?l.x+e:e,t=void 0===t?l.y:n?l.y+t:t,o({x:e,y:t})}function m(e){if(!e)return 0;return window.innerWidth/2-e.widthDimension/2-7}function h(t){"responsiveUpdate"===t.data&&"100%"===window.responsiveState.breakpoint&&p({x:m(e),y:0})}}function Tp(e={}){e.rootAttributes=e.rootAttributes??{};const[n,r]=t.exports.useState({dataName:"default",data:{},dataText:"{}",dataOptions:[],designPreview:[],errorMessage:null,loading:!1}),[a,l]=t.exports.useState(f(n.dataName,n.designPreview)),o=e=>r(Object.assign({},n,e)),[i,u]=t.exports.useState(!1);t.exports.useEffect((async()=>{await p(n.dataName)}),[]);const s=t.exports.useCallback((e=>{vp(e)&&c()}),[]);t.exports.useEffect((()=>(document.addEventListener("keydown",s),()=>{document.removeEventListener("keydown",s)})),[s]),t.exports.useEffect((()=>(window.addEventListener("message",d),()=>window.removeEventListener("message",d))),[n]),t.exports.useEffect((()=>{l(f(n.dataName,n.designPreview))}),[n.designPreview]);return M.createElement("div",{style:{display:"flex",gap:"1rem",alignItems:"center"}},M.createElement(xp,{onClick:()=>(u(!0),void setTimeout((()=>document.querySelector(".sidebar-active").focus()))),title:"Open a Sidebar with Data Options"}),M.createElement(Np,{previewOption:a}),M.createElement(wp,{className:i?"active sidebar-active":"",tabIndex:"0",onBlur:async e=>await gp(e)?c():null},M.createElement(Sp,null,M.createElement(Cp,{onClick:()=>c()})),n.dataOptions&&!!n.dataOptions.length&&M.createElement(Ep,null,M.createElement("label",{htmlFor:"data-options"},"Data Options"),M.createElement("select",{name:"data",id:"data-options",onChange:e=>async function(e){const t=e.target.value;await p(t)}(e),value:n.dataName,disabled:n.loading},n.dataOptions.map((e=>{const t=n.dataName===e;return M.createElement("option",{value:e,selected:t},e)})))),n.data&&M.createElement("textarea",{value:n.dataText,onChange:function(e){let t;try{t=JSON.parse(e.target.value)}catch(t){return void o({dataText:e.target.value,errorMessage:"Invalid JSON, please review and try again."})}o({dataText:e.target.value,data:t,errorMessage:null}),m(t)},disabled:n.loading}),n.errorMessage&&M.createElement("p",{className:"alert alert--error"},n.errorMessage),n.loading&&M.createElement("p",{className:"alert"},"Loading, please wait..."),M.createElement("div",{className:"actions"},M.createElement("button",{className:"btn btn--secondary",disabled:n.loading,onClick:e=>function(e,t){e.stopPropagation(),"string"!=typeof t&&(t=JSON.stringify(t,null,2));if(navigator.clipboard&&window.isSecureContext)return navigator.clipboard.writeText(t);{let n=document.createElement("textarea");return n.value=t,n.style.position="fixed",n.style.left="-999999px",n.style.top="-999999px",document.body.appendChild(n),n.select(),new Promise(((t,r)=>{document.execCommand("copy")?t():r(),n.remove(),e.target.focus()}))}}(e,n.data)},"Copy to Clipboard"),M.createElement("button",{className:"btn btn--secondary",disabled:n.loading,onClick:e=>function(){const e="https://blocks-registery.axe-web.com/content-generator/",t=new Headers;t.append("Content-Type","application/json");const r={method:"POST",headers:t,body:JSON.stringify({json:n.data})};return o({loading:!0,errorMessage:null}),fetch(e,r).then((e=>e.json())).then((e=>{if(console.log(e),200!==e.statusCode)throw new Error(e.message);const t=e.variation;o({dataText:JSON.stringify(t,null,2),data:t,errorMessage:
Line truncated
|
||||||
Vendored
+1
-1
@@ -18,4 +18,4 @@ function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"de
|
|||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
var $=n.exports,j=V.exports;function B(e){for(var n="https://reactjs.org/docs/error-decoder.html?invariant="+e,t=1;t<arguments.length;t++)n+="&args[]="+encodeURIComponent(arguments[t]);return"Minified React error #"+e+"; visit "+n+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var H=new Set,W={};function Q(e,n){q(e,n),q(e+"Capture",n)}function q(e,n){for(W[e]=n,e=0;e<n.length;e++)H.add(n[e])}var K=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),Y=Object.prototype.hasOwnProperty,X=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,G={},Z={};function J(e,n,t,r,l,a,o){this.acceptsBooleans=2===n||3===n||4===n,this.attributeName=r,this.attributeNamespace=l,this.mustUseProperty=t,this.propertyName=e,this.type=n,this.sanitizeURL=a,this.removeEmptyString=o}var ee={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){ee[e]=new J(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var n=e[0];ee[n]=new J(n,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){ee[e]=new J(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){ee[e]=new J(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){ee[e]=new J(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){ee[e]=new J(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){ee[e]=new J(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){ee[e]=new J(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){ee[e]=new J(e,5,!1,e.toLowerCase(),null,!1,!1)}));var ne=/[\-:]([a-z])/g;function te(e){return e[1].toUpperCase()}function re(e,n,t,r){var l=ee.hasOwnProperty(n)?ee[n]:null;(null!==l?0!==l.type:r||!(2<n.length)||"o"!==n[0]&&"O"!==n[0]||"n"!==n[1]&&"N"!==n[1])&&(function(e,n,t,r){if(null==n||function(e,n,t,r){if(null!==t&&0===t.type)return!1;switch(typeof n){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==t?!t.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,n,t,r))return!0;if(r)return!1;if(null!==t)switch(t.type){case 3:return!n;case 4:return!1===n;case 5:return isNaN(n);case 6:return isNaN(n)||1>n}return!1}(n,t,l,r)&&(t=null),r||null===l?function(e){return!!Y.call(Z,e)||!Y.call(G,e)&&(X.test(e)?Z[e]=!0:(G[e]=!0,!1))}(n)&&(null===t?e.removeAttribute(n):e.setAttribute(n,""+t)):l.mustUseProperty?e[l.propertyName]=null===t?3!==l.type&&"":t:(n=l.attributeName,r=l.attributeNamespace,null===t?e.removeAttribute(n):(t=3===(l=l.type)||4===l&&!0===t?"":""+t,r?e.setAttributeNS(r,n,t):e.setAttribute(n,t))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,"http://www.w3.org
Line truncated
|
var $=n.exports,j=V.exports;function B(e){for(var n="https://reactjs.org/docs/error-decoder.html?invariant="+e,t=1;t<arguments.length;t++)n+="&args[]="+encodeURIComponent(arguments[t]);return"Minified React error #"+e+"; visit "+n+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var H=new Set,W={};function Q(e,n){q(e,n),q(e+"Capture",n)}function q(e,n){for(W[e]=n,e=0;e<n.length;e++)H.add(n[e])}var K=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),Y=Object.prototype.hasOwnProperty,X=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,G={},Z={};function J(e,n,t,r,l,a,o){this.acceptsBooleans=2===n||3===n||4===n,this.attributeName=r,this.attributeNamespace=l,this.mustUseProperty=t,this.propertyName=e,this.type=n,this.sanitizeURL=a,this.removeEmptyString=o}var ee={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){ee[e]=new J(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var n=e[0];ee[n]=new J(n,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){ee[e]=new J(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){ee[e]=new J(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){ee[e]=new J(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){ee[e]=new J(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){ee[e]=new J(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){ee[e]=new J(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){ee[e]=new J(e,5,!1,e.toLowerCase(),null,!1,!1)}));var ne=/[\-:]([a-z])/g;function te(e){return e[1].toUpperCase()}function re(e,n,t,r){var l=ee.hasOwnProperty(n)?ee[n]:null;(null!==l?0!==l.type:r||!(2<n.length)||"o"!==n[0]&&"O"!==n[0]||"n"!==n[1]&&"N"!==n[1])&&(function(e,n,t,r){if(null==n||function(e,n,t,r){if(null!==t&&0===t.type)return!1;switch(typeof n){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==t?!t.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,n,t,r))return!0;if(r)return!1;if(null!==t)switch(t.type){case 3:return!n;case 4:return!1===n;case 5:return isNaN(n);case 6:return isNaN(n)||1>n}return!1}(n,t,l,r)&&(t=null),r||null===l?function(e){return!!Y.call(Z,e)||!Y.call(G,e)&&(X.test(e)?Z[e]=!0:(G[e]=!0,!1))}(n)&&(null===t?e.removeAttribute(n):e.setAttribute(n,""+t)):l.mustUseProperty?e[l.propertyName]=null===t?3!==l.type&&"":t:(n=l.attributeName,r=l.attributeNamespace,null===t?e.removeAttribute(n):(t=3===(l=l.type)||4===l&&!0===t?"":""+t,r?e.setAttributeNS(r,n,t):e.setAttribute(n,t))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,"http://www.w3.org
Line truncated
|
||||||
@@ -17,6 +17,8 @@ function initBlock(blockName = '', selector = '', cb) {
|
|||||||
|
|
||||||
// Data Updates Listeners.
|
// Data Updates Listeners.
|
||||||
(function () {
|
(function () {
|
||||||
|
const block = getQueryParams().block;
|
||||||
|
|
||||||
loadDataOptions();
|
loadDataOptions();
|
||||||
listenToDataOptionsUpdates();
|
listenToDataOptionsUpdates();
|
||||||
|
|
||||||
@@ -50,7 +52,10 @@ function initBlock(blockName = '', selector = '', cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadDataOptions() {
|
function loadDataOptions() {
|
||||||
const queryParameters = new URLSearchParams({name: getQueryParams().data || 'default'});
|
const queryParameters = new URLSearchParams({
|
||||||
|
block,
|
||||||
|
name: getQueryParams().data || 'default'
|
||||||
|
});
|
||||||
fetch(`/data?${queryParameters}`)
|
fetch(`/data?${queryParameters}`)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@@ -58,14 +63,12 @@ function initBlock(blockName = '', selector = '', cb) {
|
|||||||
updateBlock({data});
|
updateBlock({data});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})();
|
|
||||||
|
|
||||||
// Listen to Template updates.
|
// Listen to Template updates.
|
||||||
(function () {
|
|
||||||
initSocket();
|
initSocket();
|
||||||
|
|
||||||
function initSocket() {
|
function initSocket() {
|
||||||
const socket = window.io.connect();
|
const socket = window.io.connect('', {query: `block=${block}`});
|
||||||
|
|
||||||
socket.on('error', function (err) {
|
socket.on('error', function (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -78,60 +81,104 @@ function initBlock(blockName = '', selector = '', cb) {
|
|||||||
socket.on('templateUpdate', function (args) {
|
socket.on('templateUpdate', function (args) {
|
||||||
updateBlock({template: args.template});
|
updateBlock({template: args.template});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
function updateBlock(args = {}) {
|
socket.on('scriptUpdate', function (args) {
|
||||||
if (args.template) {
|
const tag = updateTag('block-script');
|
||||||
template = args.template; // Update state.
|
tag.onload = () => {
|
||||||
|
updateBlock({template: args.template});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('styleUpdate', function (args) {
|
||||||
|
updateTag('block-stylesheet');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.data) {
|
function updateTag(id) {
|
||||||
data = args.data; // Update state.
|
const tag = document.getElementById(id);
|
||||||
|
const wrapper = tag.parentNode;
|
||||||
|
|
||||||
|
let clone;
|
||||||
|
let attr;
|
||||||
|
if (tag.tagName === 'SCRIPT') {
|
||||||
|
clone = document.createElement('script');
|
||||||
|
clone.type = 'text/javascript';
|
||||||
|
attr = 'src';
|
||||||
|
} else if (tag.tagName === 'LINK') {
|
||||||
|
clone = document.createElement('link');
|
||||||
|
clone.rel = 'stylesheet';
|
||||||
|
attr = 'href';
|
||||||
|
}
|
||||||
|
|
||||||
|
clone.id = id;
|
||||||
|
|
||||||
|
// Add version to the stylesheet URL, make sure we override the cache and already existing version there.
|
||||||
|
clone[attr] = tag[attr].replace(/(\?v=)[^&]+/, `$1${Date.now()}`);
|
||||||
|
|
||||||
|
tag.remove();
|
||||||
|
wrapper.append(clone);
|
||||||
|
|
||||||
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!template) {
|
function updateBlock(args = {}) {
|
||||||
return;
|
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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBlock(template, data || {}, document.getElementById("hbs-container"));
|
function renderBlock(templateHbs, jsonData, target) {
|
||||||
}
|
const template = Handlebars.compile(templateHbs);
|
||||||
|
|
||||||
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) {
|
||||||
* Handlebars Helpers
|
return attr;
|
||||||
*/
|
});
|
||||||
Handlebars.registerHelper('esc_attr', function (attr) {
|
|
||||||
return attr;
|
|
||||||
});
|
|
||||||
|
|
||||||
Handlebars.registerHelper('esc_url', function (attr) {
|
Handlebars.registerHelper('esc_html', function (attr) {
|
||||||
return attr;
|
return attr;
|
||||||
});
|
});
|
||||||
|
|
||||||
Handlebars.registerHelper('esc_html', function (attr) {
|
Handlebars.registerHelper('base_url', function () {
|
||||||
return attr;
|
const list = ['block'];
|
||||||
});
|
|
||||||
|
|
||||||
Handlebars.registerHelper('base_url', function () {
|
if (block) {
|
||||||
return '/';
|
list.push(block.substr(1));
|
||||||
});
|
}
|
||||||
|
|
||||||
let html;
|
return ['', ...list, ''].join('/');
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
let html;
|
||||||
html = template(jsonData);
|
|
||||||
} catch (e) {
|
try {
|
||||||
html = `<div style="max-width: 1280px; margin: 1rem auto;">
|
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>
|
<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>
|
<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>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
target.innerHTML = html;
|
target.innerHTML = html;
|
||||||
if (reload) {
|
if (reload) {
|
||||||
reload();
|
reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})();
|
||||||
+27
-26
@@ -46,31 +46,10 @@ function SyncScreen() {
|
|||||||
</>
|
</>
|
||||||
|
|
||||||
async function ignoreVersionSync() {
|
async function ignoreVersionSync() {
|
||||||
setLoading(true);
|
// Add "ignore" query parameter to current URl and redirect.
|
||||||
|
const url = new URL(window.location.href);
|
||||||
let data = {};
|
url.searchParams.set('ignoreVersionSync', 'true');
|
||||||
try {
|
window.location = url.href;
|
||||||
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() {
|
async function runSyncLogic() {
|
||||||
@@ -78,7 +57,14 @@ function SyncScreen() {
|
|||||||
|
|
||||||
let data = {};
|
let data = {};
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/sync', {method: 'POST'});
|
const response = await fetch('/sync', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({block: getQueryParams().block}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
data = await response.json();
|
data = await response.json();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError('Error: ' + err.message);
|
setError('Error: ' + err.message);
|
||||||
@@ -95,6 +81,21 @@ function SyncScreen() {
|
|||||||
setTimeout(() => window.location.reload(), 1000);
|
setTimeout(() => window.location.reload(), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This function is used in multiple places (repeated code).
|
||||||
|
// Move to a common place.
|
||||||
|
function getQueryParams() {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const params = {};
|
||||||
|
|
||||||
|
for (const [key, value] of urlParams) {
|
||||||
|
params[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ function DataOptions(props = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchDataOptions(name = 'default') {
|
async function fetchDataOptions(name = 'default') {
|
||||||
const queryParameters = new URLSearchParams({name});
|
const queryParameters = new URLSearchParams({name, block: window.devTool.blockName});
|
||||||
const response = await fetch(`/data?${queryParameters}`);
|
const response = await fetch(`/data?${queryParameters}`);
|
||||||
return await response.json();
|
return await response.json();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ function Publish(props = {}) {
|
|||||||
export function setupPublish(rootAttributes) {
|
export function setupPublish(rootAttributes) {
|
||||||
// INIT
|
// INIT
|
||||||
const wrapper = document.createElement('div');
|
const wrapper = document.createElement('div');
|
||||||
|
wrapper.setAttribute('id', 'publish-btn');
|
||||||
document.querySelector('.page_toolbar__right').append(wrapper)
|
document.querySelector('.page_toolbar__right').append(wrapper)
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(wrapper);
|
const root = ReactDOM.createRoot(wrapper);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
{{> (include_partial "layouts/partials/head") }}
|
{{> (include_partial "layouts/partials/head") }}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ body {
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
background-color: #F7FAFC;
|
background-color: #F7FAFC;
|
||||||
}
|
}
|
||||||
|
body.view-mode #publish-btn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
--btn-color: #333;
|
--btn-color: #333;
|
||||||
|
|||||||
@@ -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;;;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"}
|
{"version":3,"sourceRoot":"","sources":["page--main.scss","_buttons.scss","_overlay.scss","_page--preview.scss"],"names":[],"mappings":"AAAA;EACE;EACA;;;AAGF;EACE;EACA;EAEA;;AAGE;EACE;;;ACbN;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;;;AFUF;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;;;AGxFJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACA;;AAEA;EACE;EAEA;EACA;;;AHuEJ;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"}
|
||||||
@@ -8,6 +8,12 @@ body {
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
//overflow: none;
|
//overflow: none;
|
||||||
background-color: #F7FAFC;
|
background-color: #F7FAFC;
|
||||||
|
|
||||||
|
&.view-mode {
|
||||||
|
#publish-btn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "buttons";
|
@import "buttons";
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@axe-web/block-dev-tool",
|
"name": "@axe-web/block-dev-tool",
|
||||||
"version": "1.0.32",
|
"version": "1.0.31",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@axe-web/block-dev-tool",
|
"name": "@axe-web/block-dev-tool",
|
||||||
"version": "1.0.32",
|
"version": "1.0.31",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@axe-web/create-block": "^1.1.30",
|
"@axe-web/create-block": "^1.1.30",
|
||||||
|
|||||||
+5
-4
@@ -1,15 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@axe-web/block-dev-tool",
|
"name": "@axe-web/block-dev-tool",
|
||||||
"version": "1.0.32",
|
"version": "1.0.31",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "AXE-WEB",
|
"name": "AXE-WEB",
|
||||||
"email": "[email protected]",
|
"email": "[email protected]",
|
||||||
"url": "https://axe-web.com/"
|
"url": "https://axe-web.com/"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"info": "BLOCK_NAME=icon-text-columns MODULE_PATH= node debug.js",
|
"info": "node debug.js",
|
||||||
"dev": "BLOCK_NAME=icon-text-columns MODULE_PATH= node server.js",
|
"dev": "node server.js",
|
||||||
"build-platform": "BLOCK_NAME=icon-text-columns MODULE_PATH= node ./build.js",
|
"view-mode": "VIEW_MODE=true node server.js",
|
||||||
|
"build-platform": "BLOCK_NAME=swiper-test MODULE_PATH= node ./build.js",
|
||||||
"dev-dev-tool": "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"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,13 +2,19 @@
|
|||||||
|
|
||||||
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>;
|
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>;
|
||||||
|
|
||||||
class <%= blockClassModel %>_Component extends \Core\Component {
|
class <%= blockClassModel %>_Component <% if (isComponentManager || isElementor) { %>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 %>';
|
||||||
|
|
||||||
function register_assets(): void {
|
<% if (!isComponentManager && !isElementor) { %>public function __construct() {
|
||||||
|
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
|
||||||
|
|
||||||
@@ -16,14 +22,12 @@ class <%= blockClassModel %>_Component extends \Core\Component {
|
|||||||
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 );
|
wp_register_script( 'block-<%= blockFilename %>', $base_path . 'templates/scripts/<%= blockFilename %>.min.js', $script_deps, self::VERSION, true );<% if (!isElementor) { %>
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
@@ -34,7 +38,7 @@ class <%= blockClassModel %>_Component extends \Core\Component {
|
|||||||
$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 );
|
||||||
}
|
}<% 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' ] );
|
||||||
@@ -43,25 +47,9 @@ class <%= blockClassModel %>_Component extends \Core\Component {
|
|||||||
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' ),
|
|
||||||
]
|
|
||||||
]
|
|
||||||
] );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<%= blockClassModel %>_Component::get_instance();
|
<% if (isComponentManager) { %><%= blockClassModel %>_Component::get_instance();<% } else {
|
||||||
// new <%= blockClassModel %>_Component();
|
%>new <%= blockClassModel %>_Component();<% } %>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?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 %>', $this->get_assets_path_url( 'templates/styles/<%= blockFilename %>.min.css' ), ['assets-style'], self::VERSION );<% if (include_script) { %>
|
||||||
|
wp_enqueue_script( 'block-<%= blockFilename %>', $this->get_assets_path_url( 'templates/scripts/<%= blockFilename %>.min.js' ), ['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' => $this->get_assets_path_url( 'templates/styles/<%= blockFilename %>.min.css' ),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'script_assets' => [
|
||||||
|
[
|
||||||
|
'name' => '<%= blockFilename %>',
|
||||||
|
'url' => $this->get_assets_path_url( 'templates/scripts/<%= blockFilename %>.min.js' ),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
] );
|
||||||
|
}
|
||||||
|
<% } %><% 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',
|
||||||
|
$this->get_assets_path_url( 'templates/gutenberg-block/build/front.js' ),
|
||||||
|
$asset_file_front['dependencies'],
|
||||||
|
$asset_file_front['version'],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
} );<% } %>
|
||||||
|
}<% } %>
|
||||||
|
}
|
||||||
|
|
||||||
|
<%= blockClassModel %>_Component::get_instance();
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AXEWEB_Blocks\Blocks\<%= ownerClass %>\<%= blockClassModel %>\Helpers;
|
||||||
|
|
||||||
|
class <%= blockClassModel %>_API {
|
||||||
|
|
||||||
|
static function prepare_args( $args = [] ) {
|
||||||
|
|
||||||
|
// $args = array_merge( [], $args );
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,10 @@ 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);
|
||||||
@@ -33,7 +37,12 @@ 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'));
|
||||||
@@ -75,21 +84,49 @@ export async function buildWordPress(blockName, args = {}) {
|
|||||||
json: await readJSONFile(path.join(projectPath, 'data', 'default.json'), "utf8"),
|
json: await readJSONFile(path.join(projectPath, 'data', 'default.json'), "utf8"),
|
||||||
});
|
});
|
||||||
|
|
||||||
await createFiles(data, [{
|
// await createFiles(Object.assign({}, data, {defaultData: phpDataObject}), [{
|
||||||
from: `templates/helpers/Template_Elementor_Widget.php`,
|
// from: `templates/helpers/Template_Defaults.php`,
|
||||||
to: `helpers/${data.blockClassModel}_Elementor_Widget.php`,
|
// to: `helpers/${data.blockClassModel}_Defaults.php`,
|
||||||
}], {
|
// }], {
|
||||||
pathDist: distPath,
|
// pathDist: distPath,
|
||||||
generatorsPath: path.join(__dirname)
|
// generatorsPath: path.join(__dirname),
|
||||||
});
|
// });
|
||||||
|
|
||||||
await createFiles(data, [{
|
if (isElementor) {
|
||||||
from: `templates/Template_Basic_Component.php`,
|
await createFiles(data, [{
|
||||||
to: `${data.blockClassModel}_Component.php`,
|
from: `templates/helpers/Template_Elementor_Widget.php`,
|
||||||
}], {
|
to: `helpers/${data.blockClassModel}_Elementor_Widget.php`,
|
||||||
pathDist: distPath,
|
}], {
|
||||||
generatorsPath: path.join(__dirname)
|
pathDist: distPath,
|
||||||
});
|
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 = '') {
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import {getBlockConfigs, getBlockName, getBlockVariations, handlebarLayoutsPath} from "../helpers.js";
|
||||||
|
import path from "path";
|
||||||
|
import {buildAssetFiles} from "../inc/changes-watcher.js";
|
||||||
|
|
||||||
|
export default async function (req, res) {
|
||||||
|
const blockName = req.query.block;
|
||||||
|
const block = getBlockName(blockName);
|
||||||
|
|
||||||
|
const blockDir = path.join('blocks', '@' + block.project, block.name);
|
||||||
|
const dataFiles = await getBlockVariations(blockDir);
|
||||||
|
|
||||||
|
const data = await getDataOfFrame(!!req.query.iframe, Object.assign({}, block, {dataFiles}));
|
||||||
|
|
||||||
|
if (data.error && data.errorMessage) {
|
||||||
|
return res.send(data.errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseView = req.params.baseView ?? 'alignfull';
|
||||||
|
|
||||||
|
await buildAssetFiles(blockDir);
|
||||||
|
|
||||||
|
res.render(baseView, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataOfFrame(isIframe = false, block) {
|
||||||
|
const data = {config: await getBlockConfigs(block)};
|
||||||
|
if (data.error && data.errorMessage) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.helpers = {
|
||||||
|
include_partial: (filesPath) => handlebarLayoutsPath(filesPath),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isIframe) {
|
||||||
|
data.iframeMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.staticFilesPath = `/block/${block.project}/${block.name}`;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import {
|
||||||
|
getBlockData,
|
||||||
|
getBlockName,
|
||||||
|
getBlockVariations,
|
||||||
|
getListOfDesignPreviewFiles,
|
||||||
|
} from "../helpers.js";
|
||||||
|
import path from "path";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
|
||||||
|
export default async function (req, res, next) {
|
||||||
|
let variationName = req.query.name ? req.query.name : 'default';
|
||||||
|
const block = getBlockName(req.query.block);
|
||||||
|
|
||||||
|
const blockDir = path.join('blocks', '@' + block.project, block.name);
|
||||||
|
const dataFiles = await getBlockVariations(blockDir);
|
||||||
|
const data = await getBlockData(variationName, {projectPath: blockDir});
|
||||||
|
|
||||||
|
let designPreviewFiles = [];
|
||||||
|
try {
|
||||||
|
designPreviewFiles = getListOfDesignPreviewFiles(variationName, await fs.readdir(path.join(blockDir, 'design', 'preview')), block);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Preview Design doesn\'t exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
dataOptions: dataFiles,
|
||||||
|
designPreview: designPreviewFiles,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import {getBlockConfigs, getBlockName, getBlockVariations, handlebarLayoutsPath, verifyVersion} from "../helpers.js";
|
||||||
|
import path from "path";
|
||||||
|
import {REGISTRY_URL} from "@axe-web/create-block/env.js";
|
||||||
|
|
||||||
|
export async function index(req, res, next) {
|
||||||
|
|
||||||
|
const blockName = req.query.block;
|
||||||
|
const block = getBlockName(blockName);
|
||||||
|
|
||||||
|
const blockDir = path.join('blocks', '@' + block.project, block.name);
|
||||||
|
const dataFiles = await getBlockVariations(blockDir);
|
||||||
|
|
||||||
|
const data = await getBlockConfigs(Object.assign({}, block, {dataFiles}));
|
||||||
|
|
||||||
|
if (data.error && data.errorMessage) {
|
||||||
|
// TODO: Throw Error.
|
||||||
|
}
|
||||||
|
|
||||||
|
data.helpers = {
|
||||||
|
include_partial: (filesPath) => handlebarLayoutsPath('.', filesPath),
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make sure we sync block before we start working on it.
|
||||||
|
try {
|
||||||
|
const verifiedVersion = await verifyVersion(blockName, blockDir, REGISTRY_URL);
|
||||||
|
if (!verifiedVersion && !req.query['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.blockName = blockName;
|
||||||
|
data.baseView = 'alignfull';
|
||||||
|
data.port = `/view/${data.baseView}`;
|
||||||
|
|
||||||
|
let previewFrameUrl = ``; // This variable is used in `*.hbs` and it will be updated once BrowserSync is ready.
|
||||||
|
data.previewFrameUrl = `${previewFrameUrl}${data.port}`;
|
||||||
|
data.previewFrameUrlNewWindow = `${previewFrameUrl}${data.port}`;
|
||||||
|
data.shareUrl = '';
|
||||||
|
|
||||||
|
data.viewMode = process.env.VIEW_MODE ?? false;
|
||||||
|
|
||||||
|
res.render('index', data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export default async function (req, res, next) {
|
||||||
|
|
||||||
|
if (process.env.VIEW_MODE) {
|
||||||
|
throw new Error("Can't publish in view mode.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
export function staticFiles(req, res) {
|
||||||
|
const fileName = req.params[0];
|
||||||
|
const path = `blocks/@${req.params.project}/${req.params.blockName}/src/${fileName}`;
|
||||||
|
|
||||||
|
return deliverStaticFile(path, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function previewFiles(req, res) {
|
||||||
|
const fileName = req.params[0];
|
||||||
|
const path = `blocks/@${req.params.project}/${req.params.blockName}/design/${fileName}`;
|
||||||
|
|
||||||
|
return deliverStaticFile(path, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deliverStaticFile(path, res) {
|
||||||
|
// If file doesn't exist, return 404.
|
||||||
|
res.sendFile(path, {root: './'}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
res.send('File not found.');
|
||||||
|
res.status(err.status).end();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import {syncFilesWithCloud} from "../helpers.js";
|
||||||
|
|
||||||
|
export default async function (req, res, next) {
|
||||||
|
try {
|
||||||
|
await syncFilesWithCloud(req.body.block, null, true);
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).json({status: 500, message: err.message});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({status: 200, message: 'Successfully synced!'});
|
||||||
|
}
|
||||||
@@ -1,604 +1,35 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import {PRODUCTION_REGISTRY_URL} from "./env.js";
|
import {init} from "./inc/server.js";
|
||||||
import path from 'path';
|
import {index} from "./routes/index.js";
|
||||||
import fetch from "node-fetch";
|
import dataRoute from "./routes/data.js";
|
||||||
import express from 'express';
|
import baseView from "./routes/base-view.js";
|
||||||
import {create} from 'express-handlebars';
|
import syncRoute from "./routes/sync.js";
|
||||||
import browserSync from 'browser-sync';
|
import publishRoute from "./routes/publish.js";
|
||||||
import config from 'config';
|
import {ViewSync} from "./inc/view-sync.js";
|
||||||
import gulp from 'gulp';
|
import {previewFiles, staticFiles} from "./routes/static-files.js";
|
||||||
import babel from "gulp-babel";
|
import {setupWatcher} from "./inc/changes-watcher.js";
|
||||||
import uglify from "gulp-uglify";
|
|
||||||
import rename from "gulp-rename";
|
|
||||||
import dartSass from 'sass';
|
|
||||||
import gulpSass from 'gulp-sass';
|
|
||||||
import sourcemaps from "gulp-sourcemaps";
|
|
||||||
import fs from "fs/promises";
|
|
||||||
import open from "open";
|
|
||||||
import {sanitizeUrl} from "@braintree/sanitize-url";
|
|
||||||
import sanitizeHtml from 'sanitize-html';
|
|
||||||
import {escape} from "lodash-es";
|
|
||||||
import {
|
|
||||||
getBlockConfigs,
|
|
||||||
getBlockData,
|
|
||||||
getBlockName,
|
|
||||||
getConfigs,
|
|
||||||
getImagesList,
|
|
||||||
isFileEmpty,
|
|
||||||
readJSONFile,
|
|
||||||
removeCommentsFromCss,
|
|
||||||
removeCommentsFromJs,
|
|
||||||
replaceNames,
|
|
||||||
syncFilesWithCloud,
|
|
||||||
uploadFile,
|
|
||||||
verifyVersion,
|
|
||||||
zipProject
|
|
||||||
} from "./helpers.js";
|
|
||||||
import PluginError from 'plugin-error';
|
|
||||||
import {Server} from "socket.io";
|
|
||||||
import {createServer} from 'http';
|
|
||||||
import {authtoken, connect} from "ngrok";
|
|
||||||
import bodyParser from "body-parser";
|
|
||||||
|
|
||||||
/**
|
const {expressApp, httpServer} = init();
|
||||||
* Constants
|
|
||||||
*/
|
|
||||||
|
|
||||||
const {isDev, modulesPath, projectPath, developmentBlockName} = getConfigs();
|
const viewSync = new ViewSync(httpServer);
|
||||||
const blocksRegistry = isDev ? 'http://localhost:3020' : PRODUCTION_REGISTRY_URL;
|
setupWatcher(viewSync);
|
||||||
const DevToolToken = 'D9lgz0TvzXCnp0xnwVBL109DaAR6Puk6F7YewDhgmP8='; // Temporary token for development purposes.
|
|
||||||
|
|
||||||
const dataFiles = await getDataFiles(projectPath);
|
const PORT = process.env.PORT || 3010;
|
||||||
const DEFAULT_VIEW_LAYOUT = 'alignfull';
|
|
||||||
|
|
||||||
/**
|
httpServer.listen(PORT, '0.0.0.0', () => {
|
||||||
* State
|
console.log(`Server app listening on port ${PORT}`)
|
||||||
*/
|
|
||||||
|
|
||||||
let port = 3000; // 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 = '';
|
|
||||||
const sessions = [];
|
|
||||||
let ignoreVersionSync = false;
|
|
||||||
let bs;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init server
|
|
||||||
*/
|
|
||||||
|
|
||||||
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);
|
|
||||||
initSessionsServer(httpServer);
|
|
||||||
|
|
||||||
const sass = gulpSass(dartSass);
|
|
||||||
|
|
||||||
const hbs = create({
|
|
||||||
extname: '.hbs', defaultLayout: false, partialsDir: ['.'], helpers: {
|
|
||||||
esc_attr(attr) {
|
|
||||||
return escape(attr);
|
|
||||||
}, esc_url(url) {
|
|
||||||
return sanitizeUrl(url);
|
|
||||||
}, esc_html(html) {
|
|
||||||
// TODO: Check if we can remove this helper.
|
|
||||||
return html;
|
|
||||||
}, safe_html(html) {
|
|
||||||
return sanitizeHtml(html);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.engine('.hbs', hbs.engine);
|
// Middleware
|
||||||
app.set('view engine', '.hbs');
|
// expressApp.use(setHeaders);
|
||||||
app.set('views', path.join(modulesPath, 'layouts'));
|
|
||||||
|
|
||||||
//
|
|
||||||
// Routes
|
// Routes
|
||||||
//
|
expressApp.get('/', index);
|
||||||
|
expressApp.get('/data', dataRoute);
|
||||||
|
expressApp.get('/view/:baseView', baseView);
|
||||||
|
expressApp.get('/design/:project/:blockName/*', previewFiles);
|
||||||
|
expressApp.get('/block/:project/:blockName/*', staticFiles);
|
||||||
|
expressApp.post('/sync', syncRoute);
|
||||||
|
expressApp.get('/publish', publishRoute);
|
||||||
|
|
||||||
app.get('/', async (req, res, next) => {
|
|
||||||
const data = getBlockConfigs({modulesPath, dataFiles});
|
|
||||||
if (data.error && data.errorMessage) {
|
|
||||||
return res.send(data.errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseView = config.has('baseView') ? config.get('baseView') : DEFAULT_VIEW_LAYOUT;
|
|
||||||
const baseViewUrl = `view/${baseView}`;
|
|
||||||
|
|
||||||
data.helpers = {
|
|
||||||
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.port = `/${baseViewUrl}`;
|
|
||||||
data.previewFrameUrl = `${previewFrameUrl}/${baseViewUrl}`;
|
|
||||||
data.shareUrl = shareUrl;
|
|
||||||
|
|
||||||
// TODO: Need to review this logic, conflicts with the browsersync work after "/sync" action.
|
|
||||||
// if (req.headers.referer) {
|
|
||||||
// // NGROK, public URL
|
|
||||||
// data.shareUrl = undefined; // Link already shared.
|
|
||||||
// data.previewFrameUrl = `/${baseViewUrl}`;
|
|
||||||
// data.publicUrl = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
res.render('index', data);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/view/:baseView', (req, res) => {
|
|
||||||
const data = getDataOfFrame(!!req.query.iframe);
|
|
||||||
|
|
||||||
if (data.error && data.errorMessage) {
|
|
||||||
return res.send(data.errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseView = req.params.baseView ?? DEFAULT_VIEW_LAYOUT;
|
|
||||||
|
|
||||||
res.render(baseView, data)
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/publish', async (req, res) => {
|
|
||||||
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 = {
|
|
||||||
uploadBundleUrl: undefined,
|
|
||||||
staticFilesUrls: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(`${blocksRegistry}`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
headers: {'Content-Type': 'application/json'}
|
|
||||||
});
|
|
||||||
|
|
||||||
responseData = await response.json();
|
|
||||||
} catch (e) {
|
|
||||||
res.json({success: false, message: 'Blocks Registry server is not available.'});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (responseData.statusCode !== 200) {
|
|
||||||
res.json({success: false, message: 'Error on registry level.'});
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uploadStaticFiles) {
|
|
||||||
if (responseData.staticFilesUrls.css) {
|
|
||||||
await uploadFile(
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await syncFilesWithCloud(path.join(projectPath, 'block.json'), bs);
|
|
||||||
} catch (err) {
|
|
||||||
res.json({success: false, message: err});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.json({success: true});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/data', async (req, res) => {
|
|
||||||
let jsonDataFileName = req.query.name ? req.query.name : 'default';
|
|
||||||
|
|
||||||
const dataFiles = await getDataFiles(projectPath);
|
|
||||||
const data = await getBlockData(jsonDataFileName, {projectPath});
|
|
||||||
|
|
||||||
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,
|
|
||||||
designPreview: designPreviewFiles,
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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
|
|
||||||
app.use(handleSyntaxErrors);
|
|
||||||
|
|
||||||
// Static Files
|
|
||||||
app.use(express.static(path.join(projectPath, 'src')));
|
|
||||||
app.use(express.static(path.join(projectPath, 'design')));
|
|
||||||
app.use(express.static(path.join(modulesPath, 'layouts')));
|
|
||||||
|
|
||||||
// Custom Middleware
|
|
||||||
app.use(setHeaders);
|
|
||||||
|
|
||||||
// Setup Gulp
|
|
||||||
await buildAssetFiles();
|
|
||||||
|
|
||||||
// BrowserSync
|
|
||||||
shareUrl = await getShareableUrl();
|
|
||||||
const bsOptions = await startBrowserSync();
|
|
||||||
port = bsOptions.port;
|
|
||||||
previewFrameUrl = bsOptions.previewFrameUrl;
|
|
||||||
await open(bsOptions.devToolUrl);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Functions
|
|
||||||
//
|
|
||||||
|
|
||||||
function getListOfDesignPreviewFiles(jsonDataFileName, previewFiles) {
|
|
||||||
return previewFiles
|
|
||||||
.filter(fileName => {
|
|
||||||
return fileName.startsWith(jsonDataFileName + '.');
|
|
||||||
})
|
|
||||||
.map(fileName => {
|
|
||||||
const fileData = fileName.split('.');
|
|
||||||
const fileFormat = fileData.pop();
|
|
||||||
const previewSize = fileData.pop();
|
|
||||||
|
|
||||||
return {
|
|
||||||
dataSource: jsonDataFileName,
|
|
||||||
widthDimension: Number.parseInt(previewSize, 10),
|
|
||||||
url: `/preview/${fileName}`,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const listener = httpServer.listen(0, async () => {
|
|
||||||
const PORT = listener.address().port;
|
|
||||||
|
|
||||||
console.log(`The web server has started on port ${PORT}`);
|
|
||||||
|
|
||||||
// BS is global variable.
|
|
||||||
bs = browserSync.create();
|
|
||||||
|
|
||||||
const files = getJSBundleFiles();
|
|
||||||
gulp.watch(files, {delay: 400}, gulp.series(['build-script-files', function (cb) {
|
|
||||||
browserSyncReload(bs, 'js', 'Script Files Change');
|
|
||||||
return cb();
|
|
||||||
}]));
|
|
||||||
|
|
||||||
gulp.watch(path.posix.join(projectPath, "src/**/*.scss"), {delay: 400}, gulp.series(['build-styling-files', function (cb) {
|
|
||||||
browserSyncReload(bs, 'css', 'Style Files Change');
|
|
||||||
return cb();
|
|
||||||
}]));
|
|
||||||
|
|
||||||
bs.watch(path.join(projectPath, "src/**/*.hbs"), function () {
|
|
||||||
return syncTemplate(sessions);
|
|
||||||
});
|
|
||||||
|
|
||||||
const args = {
|
|
||||||
proxy: `http://localhost:${PORT}`,
|
|
||||||
open: false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (shareUrl) {
|
|
||||||
args.socket = {
|
|
||||||
domain: shareUrl
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
bs.init(args, (err, bs) => {
|
|
||||||
if (err) {
|
|
||||||
return reject(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = bs.getOptions().toJS();
|
|
||||||
|
|
||||||
const urls = {
|
|
||||||
devTool: options.urls.local.replace(options.port, options.proxy.url.port),
|
|
||||||
previewFrame: options.urls.local,
|
|
||||||
};
|
|
||||||
|
|
||||||
// If local network is available.
|
|
||||||
if (options.urls.external) {
|
|
||||||
urls.devTool = options.urls.external.replace(options.port, options.proxy.url.port);
|
|
||||||
urls.previewFrame = options.urls.external;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve({
|
|
||||||
devToolUrl: urls.devTool,
|
|
||||||
previewFrameUrl: urls.previewFrame,
|
|
||||||
port: options.port
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function browserSyncReload(bs, extension = '', message = '') {
|
|
||||||
if (isDev) {
|
|
||||||
// console.log(event, file);
|
|
||||||
console.log(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extension) {
|
|
||||||
extension = "*." + extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
bs.reload(extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getJSBundleFiles() {
|
|
||||||
return [path.posix.join(projectPath, "src/**/*.js"), path.posix.join(projectPath, "src/**/*.mjs"), "!" + path.posix.join(projectPath, "src/**/*.min.js")];
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildScriptFiles(done) {
|
|
||||||
const files = getJSBundleFiles();
|
|
||||||
return gulp.src(files, {base: path.posix.join(projectPath, 'src')})
|
|
||||||
.pipe(sourcemaps.init({}))
|
|
||||||
.pipe(babel()).on('error', function (error) {
|
|
||||||
showError(new PluginError('JavaScript', error).toString());
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.pipe(gulp.src(path.join(projectPath, 'vendor/*.js')))
|
|
||||||
// .pipe(gulp.dest('src/'))
|
|
||||||
.pipe(rename({extname: '.min.js'}))
|
|
||||||
.pipe(uglify())
|
|
||||||
.pipe(sourcemaps.write('.'))
|
|
||||||
.pipe(gulp.dest(path.posix.join(projectPath, 'src')));
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildStyleFiles(done) {
|
|
||||||
return gulp.src(path.join(projectPath, 'src/**/*.scss'), {base: path.posix.join(projectPath, 'src')})
|
|
||||||
.pipe(sourcemaps.init({}))
|
|
||||||
.pipe(sass.sync({outputStyle: 'compressed'}).on('error', function (error) {
|
|
||||||
showError(new PluginError('SCSS', error.messageFormatted).toString());
|
|
||||||
// sass.logError(error);
|
|
||||||
done();
|
|
||||||
}))
|
|
||||||
// .pipe(gulp.dest('src/'))
|
|
||||||
.pipe(rename({extname: '.min.css'}))
|
|
||||||
.pipe(sourcemaps.write('.', {}))
|
|
||||||
.pipe(gulp.dest(path.posix.join(projectPath, 'src')))
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildAssetFiles() {
|
|
||||||
// Register tasks.
|
|
||||||
gulp.task('build-script-files', buildScriptFiles);
|
|
||||||
gulp.task('build-styling-files', buildStyleFiles);
|
|
||||||
|
|
||||||
// Run first build.
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
gulp.series('build-script-files', 'build-styling-files', function () {
|
|
||||||
resolve();
|
|
||||||
})();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showError(errorMessage) {
|
|
||||||
console.log(errorMessage);
|
|
||||||
|
|
||||||
// TODO: Send this message to browser.
|
|
||||||
// So the developer can understand there is an error.
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareListOfDataFiles(dataFiles) {
|
|
||||||
return dataFiles
|
|
||||||
.filter((fileName) => fileName.split('.').pop() === 'json')
|
|
||||||
.map((fileName) => {
|
|
||||||
const splitName = fileName.split('.');
|
|
||||||
splitName.pop();
|
|
||||||
return splitName.join('');
|
|
||||||
})
|
|
||||||
.sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSyntaxErrors(err, req, res, next) {
|
|
||||||
if (err) {
|
|
||||||
return res.render('error', {
|
|
||||||
helpers: {
|
|
||||||
include_partial: (filesPath) => path.join(modulesPath, filesPath),
|
|
||||||
},
|
|
||||||
err
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlebarLayoutsPath() {
|
|
||||||
return path.join(...arguments)
|
|
||||||
.replace(/\\/g, '/'); // Windows path issue. Fix all "\" for Handlebars.
|
|
||||||
}
|
|
||||||
|
|
||||||
function initSessionsServer(httpServer) {
|
|
||||||
const io = new Server(httpServer);
|
|
||||||
io.on('connection', async (socket) => {
|
|
||||||
sessions.push(socket);
|
|
||||||
await syncTemplate(sessions);
|
|
||||||
});
|
|
||||||
|
|
||||||
return httpServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setHeaders(req, res, next) {
|
|
||||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function syncTemplate(sessions = []) {
|
|
||||||
const blockName = config.has('blockName') ? config.get('blockName') : developmentBlockName;
|
|
||||||
const hbsTemplate = await fs.readFile(handlebarLayoutsPath(projectPath, 'src', `${blockName}.template.hbs`), 'utf8');
|
|
||||||
|
|
||||||
sessions.forEach(socket => {
|
|
||||||
socket.emit('templateUpdate', {template: hbsTemplate});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getShareableUrl() {
|
|
||||||
let domain = PRODUCTION_REGISTRY_URL;
|
|
||||||
let data = {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(`${domain}/dev-tool/?devToolToken=${DevToolToken}`);
|
|
||||||
data = await response.json();
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Error:', `Can't load data from DevTool endpoint: ${domain}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.statusCode !== 200) {
|
|
||||||
console.log('Reply from DevTool endpoint:', data.message);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url;
|
|
||||||
try {
|
|
||||||
await authtoken(data.ngrokApiToken);
|
|
||||||
url = await connect(port);
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Error:', `Can't connect to ngrok, probably wrong token.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
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