feature: migrate to esbuild

This commit is contained in:
coderaiser 2023-01-30 12:58:21 +02:00
parent ed9af6d7a6
commit 16862719b2
12 changed files with 331 additions and 271 deletions

51
build.mjs Normal file
View file

@ -0,0 +1,51 @@
âˆimport * as esbuild from 'esbuild'
const dir = './client';
const dirModules = './client/modules';
await esbuild.build({
entryPoints: [
`${dir}/cloudcmd.js`,
`${dirModules}/edit.js`,
`${dirModules}/edit-file.js`,
`${dirModules}/edit-file-vim.js`,
`${dirModules}/edit-names.js`,
`${dirModules}/edit-names-vim.js`,
`${dirModules}/menu.js`,
`${dirModules}/view/index.js`,
`${dirModules}/help.js`,
`${dirModules}/markdown.js`,
`${dirModules}/config/index.js`,
`${dirModules}/contact.js`,
`${dirModules}/upload.js`,
`${dirModules}/operation/index.js`,
`${dirModules}/konsole.js`,
`${dirModules}/terminal.js`,
`${dirModules}/terminal-run.js`,
`${dirModules}/cloud.js`,
`${dirModules}/user-menu/index.js`,
`${dirModules}/polyfill.js`,
`${dirModules}/command-line.js`,
'css/columns/name-size-date.css',
'css/columns/name-size.css',
],
entryNames: '[dir]',
bundle: true,
minify: true,
sourcemap: true,
target: ['chrome100'],
alias: {
path: 'path-browserify',
},
outdir: 'dist',
loader: {
'.png': 'dataurl',
'.gif': 'dataurl',
'.woff': 'dataurl',
'.woff2': 'dataurl',
'.ttf': 'dataurl',
'.eot': 'dataurl',
'.svg': 'text',
}
})

View file

@ -39,60 +39,60 @@ load.addErrorListener((e, src) => {
function CloudCmdProto(DOM) {
let Listeners;
Emitify.call(this);
const CloudCmd = this;
const Info = DOM.CurrentInfo;
const {
Storage,
Files,
} = DOM;
this.log = (...a) => {
if (!isDev)
return;
console.log(...a);
};
this.prefix = '';
this.prefixSocket = '';
this.prefixURL = '';
this.DIRCLIENT = '/dist/';
this.DIRCLIENT_MODULES = this.DIRCLIENT + 'modules/';
this.DIR_CLIENT = '/dist/client';
this.DIR_CLIENT_MODULES = this.DIR_CLIENT + '/modules';
this.MIN_ONE_PANEL_WIDTH = 1155;
this.HOST = location.origin || location.protocol + '//' + location.host;
this.TITLE = 'Cloud Commander';
this.sort = {
left: 'name',
right: 'name',
};
this.order = {
left: 'asc',
right: 'asc',
};
this.changeDir = async (path, {isRefresh, panel, history = true, noCurrent, currentName} = {}) => {
const refresh = isRefresh;
let panelChanged;
if (!noCurrent && panel && panel !== Info.panel) {
DOM.changePanel();
panelChanged = true;
}
let imgPosition;
if (panelChanged || refresh || !history)
imgPosition = 'top';
Images.show.load(imgPosition, panel);
/* загружаем содержимое каталога */
await ajaxLoad(addSlashToEnd(path), {
refresh,
@ -101,7 +101,7 @@ function CloudCmdProto(DOM) {
currentName,
}, panel);
};
/**
* Конструктор CloudClient, который
* выполняет весь функционал по
@ -111,7 +111,7 @@ function CloudCmdProto(DOM) {
CloudCmd.prefix = prefix;
CloudCmd.prefixURL = `${prefix}${apiURL}`;
CloudCmd.prefixSocket = config.prefixSocket;
CloudCmd.config = (key) => config[key];
CloudCmd.config.if = currify((key, fn, a) => config[key] && fn(a));
CloudCmd._config = (key, value) => {
@ -119,61 +119,63 @@ function CloudCmdProto(DOM) {
* should be called from config.js only
* after successful update on server
*/
if (key === 'password')
return;
config[key] = value;
};
if (config.oneFilePanel)
CloudCmd.MIN_ONE_PANEL_WIDTH = Infinity;
if (!document.body.scrollIntoViewIfNeeded)
await load.js(prefix + CloudCmd.DIRCLIENT_MODULES + 'polyfill.js');
await load.js(`${prefix}${CloudCmd.DIR_CLIENT_MODULES}/polyfill.js`);
await initModules();
await baseInit();
await loadStyle();
//await loadStyle();
CloudCmd.route(location.hash);
};
/*
async function loadStyle() {
const {prefix} = CloudCmd;
const name = prefix + '/dist/cloudcmd.common.css';
const name = prefix + '/build/cloudcmd.css';
await load.css(name);
}
*/
this.route = (path) => {
const query = path.split('/');
if (!path)
return;
const [kebabModule] = query;
const module = noJS(pascalCase(kebabModule.slice(1)));
const file = query[1];
const current = DOM.getCurrentByName(file);
if (file && !current) {
const msg = formatMsg('set current file', file, 'error');
CloudCmd.log(msg);
return;
}
DOM.setCurrentFile(current);
CloudCmd.execFromModule(module, 'show');
};
this.logOut = async () => {
const url = CloudCmd.prefix + '/logout';
const error = () => document.location.reload();
const {prefix} = CloudCmd;
await DOM.Storage.clear();
unregisterSW(prefix);
DOM.load.ajax({
@ -181,19 +183,19 @@ function CloudCmdProto(DOM) {
error,
});
};
const initModules = async () => {
CloudCmd.Key = Key;
CloudCmd.Key.bind();
const [, modules] = await tryToCatch(Files.get, 'modules');
const showLoad = Images.show.load;
const doBefore = {
edit: showLoad,
menu: showLoad,
};
const load = (name, path, dobefore) => {
loadModule({
name,
@ -201,28 +203,28 @@ function CloudCmdProto(DOM) {
dobefore,
});
};
if (!modules)
return;
for (const module of modules.local) {
load(null, module, doBefore[module]);
}
};
async function saveCurrentName(currentName) {
await Storage.set('current-name', currentName);
}
async function baseInit() {
const files = DOM.getFiles();
CloudCmd.on('current-file', DOM.updateCurrentInfo);
CloudCmd.on('current-name', saveCurrentName);
const name = await Storage.get('current-name');
const currentFile = name && DOM.getCurrentByName(name) || files[0];
/* выделяем строку с первым файлом */
if (files)
DOM.setCurrentFile(currentFile, {
@ -231,56 +233,56 @@ function CloudCmdProto(DOM) {
// overwre otherwise
history: !location.hash,
});
const dirPath = DOM.getCurrentDirPath();
Listeners = CloudCmd.Listeners;
Listeners.init();
const panels = getPanels();
panels.forEach(Listeners.setOnPanel);
Listeners.initKeysPanel();
if (!CloudCmd.config('dirStorage'))
return;
const data = await Storage.get(dirPath);
if (!data)
await Storage.setJson(dirPath, getJsonFromFileTable());
}
function getPanels() {
const panels = ['left'];
if (CloudCmd.config('oneFilePanel'))
return panels;
return [
...panels,
'right',
];
}
this.execFromModule = async (moduleName, funcName, ...args) => {
await CloudCmd[moduleName]();
const func = CloudCmd[moduleName][funcName];
func(...args);
};
this.refresh = async (options = {}) => {
const {
panel = Info.panel,
currentName,
} = options;
const path = DOM.getCurrentDirPath(panel);
const isRefresh = true;
const history = false;
const noCurrent = options ? options.noCurrent : false;
await CloudCmd.changeDir(path, {
isRefresh,
history,
@ -289,7 +291,7 @@ function CloudCmdProto(DOM) {
currentName,
});
};
/**
* Функция загружает json-данные о Файловой Системе
* через ajax-запрос.
@ -302,49 +304,49 @@ function CloudCmdProto(DOM) {
*/
async function ajaxLoad(path, options = {}, panel) {
const {RESTful} = DOM;
CloudCmd.log('reading dir: "' + path + '";');
const dirStorage = CloudCmd.config('dirStorage');
const json = dirStorage && await Storage.getJson(path);
const name = options.currentName || Info.name;
const {
noCurrent,
refresh,
} = options;
if (!refresh && json)
return await createFileTable(json, panel, options);
const position = DOM.getPanelPosition(panel);
const sort = CloudCmd.sort[position];
const order = CloudCmd.order[position];
const query = rendy('?sort={{ sort }}&order={{ order }}', {
sort,
order,
});
const [, newObj] = await RESTful.read(path + query, 'json');
if (!newObj)
return; // that's OK, error handled by RESTful
options.sort = sort;
options.order = order;
await createFileTable(newObj, panel, options);
if (refresh && !noCurrent)
DOM.setCurrentByName(name);
if (!CloudCmd.config('dirStorage'))
return;
Storage.setJson(path, newObj);
}
/**
* Функция строит файловую таблицу
* @param json - данные о файлах
@ -357,36 +359,36 @@ function CloudCmdProto(DOM) {
history,
noCurrent,
} = options;
const names = [
'file',
'path',
'link',
'pathLink',
];
const [
error,
[file, path, link, pathLink],
] = await tryToCatch(Files.get, names);
if (error)
return DOM.Dialog.alert(error.responseText);
const panel = panelParam || DOM.getPanel();
const {prefix} = CloudCmd;
const {
dir,
name,
} = Info;
const {childNodes} = panel;
let i = childNodes.length;
while (i--)
panel.removeChild(panel.lastChild);
panel.innerHTML = buildFromJSON({
sort : options.sort,
order : options.order,
@ -400,26 +402,26 @@ function CloudCmdProto(DOM) {
link,
},
});
Listeners.setOnPanel(panel);
if (!noCurrent) {
let current;
if (name === '..' && dir !== '/')
current = DOM.getCurrentByName(dir);
if (!current)
[current] = DOM.getFiles(panel);
DOM.setCurrentFile(current, {
history,
});
CloudCmd.emit('active-dir', Info.dirPath);
}
}
this.goToParentDir = async () => {
const {
dir,
@ -427,17 +429,17 @@ function CloudCmdProto(DOM) {
parentDirPath,
panel,
} = Info;
if (dirPath === parentDirPath)
return;
const path = parentDirPath;
await CloudCmd.changeDir(path);
const current = DOM.getCurrentByName(dir);
const [first] = DOM.getFiles(panel);
DOM.setCurrentFile(current || first, {
history,
});

View file

@ -50,8 +50,7 @@ const onUpdateFound = wraptile(async (config) => {
const {DOM} = window;
const prefix = getPrefix(config.prefix);
await load.js(`${prefix}/dist/cloudcmd.common.js`);
await load.js(`${prefix}/dist/cloudcmd.js`);
await load.js(`${prefix}/dist/client/cloudcmd.js`);
console.log('cloudcmd: sw: updated');

View file

@ -16,45 +16,45 @@ const noJS = (a) => a.replace(/.js$/, '');
module.exports = function loadModule(params) {
if (!params)
return;
const {path} = params;
const name = path && noJS(pascalCase(path));
const doBefore = params.dobefore;
if (CloudCmd[name])
return;
CloudCmd[name] = () => {
exec(doBefore);
const {prefix} = CloudCmd;
const pathFull = prefix + CloudCmd.DIRCLIENT_MODULES + path + '.js';
const pathFull = `${prefix}${CloudCmd.DIR_CLIENT_MODULES}/${path}.js`;
return loadJS(pathFull).then(async () => {
const newModule = async (f) => f && f();
const module = CloudCmd[name];
Object.assign(newModule, module);
CloudCmd[name] = newModule;
CloudCmd.log('init', name);
await module.init();
return newModule;
});
};
CloudCmd[name].show = async (...args) => {
CloudCmd.log('show', name, args);
const m = CloudCmd[name];
const [e, a] = await tryToCatch(m);
if (e)
return console.error(e);
return await a.show(...args);
};
};

View file

@ -1,19 +1,21 @@
/* global CloudCmd, DOM */
'use strict';
/* global CloudCmd, DOM */
const exec = require('execon');
const wrap = require('wraptile');
const supermenu = require('supermenu');
const createElement = require('@cloudcmd/create-element');
const load = require('load.js');
const {FS} = require('../../common/cloudfunc');
const {getIdBySrc} = require('../dom/load');
const RESTful = require('../dom/rest');
const {
config,
Key,
prefix,
DIR_CLIENT_MODULES,
} = CloudCmd;
const {
@ -35,23 +37,24 @@ module.exports.ENABLED = false;
CloudCmd.Menu = exports;
module.exports.init = () => {
module.exports.init = async () => {
await load.css(`${prefix}${DIR_CLIENT_MODULES}/menu.css`);
const {
isAuth,
menuDataFile,
} = getFileMenuData();
const fm = DOM.getFM();
const menuData = getMenuData(isAuth);
const options = getOptions({type: 'context'});
const optionsFile = getOptions({type: 'file'});
MenuContext = supermenu(fm, options, menuData);
MenuContextFile = supermenu(fm, optionsFile, menuDataFile);
MenuContext.addContextMenuListener();
MenuContextFile.addContextMenuListener();
Events.addKey(listener);
};
@ -64,10 +67,10 @@ function hide() {
module.exports.show = (position) => {
const {x, y} = getPosition(position);
MenuContext.show(x, y);
MenuContextFile.show(x, y);
Images.hide();
};
@ -77,33 +80,33 @@ function getPosition(position) {
x: position.x,
y: position.y,
};
return getCurrentPosition();
}
function getMenuNameByEl(el) {
if (!el)
return 'context';
const name = DOM.getCurrentName(el);
if (name === '..')
return 'context';
return 'contextFile';
}
function getOptions({type}) {
let name;
let func;
if (type === 'context') {
name = 'context';
func = Key.unsetBind;
} else if (type === 'file') {
name = 'contextFile';
}
const options = {
icon : true,
beforeClose : Key.setBind,
@ -111,7 +114,7 @@ function getOptions({type}) {
beforeClick,
name,
};
return options;
}
@ -128,16 +131,16 @@ function getMenuData(isAuth) {
'Upload From Cloud': uploadFromCloud,
'(Un)Select All': DOM.toggleAllSelectedFiles,
};
if (isAuth)
menu['Log Out'] = CloudCmd.logOut;
return menu;
}
function getFileMenuData() {
const isAuth = CloudCmd.config('auth');
const menuBottom = getMenuData(isAuth);
const menuTop = {
'View': () => {
@ -168,12 +171,12 @@ function getFileMenuData() {
isCurrent(Buffer.copy, alertNoFiles);
},
};
const menuDataFile = {
...menuTop,
...menuBottom,
};
return {
isAuth,
menuDataFile,
@ -183,21 +186,21 @@ function getFileMenuData() {
function isCurrent(yesFn, noFn) {
if (Info.name !== '..')
return yesFn();
noFn();
}
function isPath(x, y) {
const {panel} = Info;
const isEmptyRoot = !panel;
if (isEmptyRoot)
return false;
const el = document.elementFromPoint(x, y);
const elements = panel.querySelectorAll('[data-name="js-path"] *');
const is = ~[].indexOf.call(elements, el);
return is;
}
@ -207,22 +210,22 @@ function beforeShow(callback, params) {
x: params.x,
y: params.y,
});
const menuName = getMenuNameByEl(el);
let isShow = menuName !== 'contextFile';
if (params.name === 'contextFile')
isShow = !isShow;
if (isShow)
MenuShowedName = name;
exec(callback);
if (isShow)
isShow = isPath(params.x, params.y);
return isShow;
}
@ -232,26 +235,26 @@ function beforeClick(name) {
async function _uploadTo(nameModule) {
const [error, data] = await Info.getData();
if (error)
return;
const {name} = Info;
CloudCmd.execFromModule(nameModule, 'uploadFile', name, data);
CloudCmd.log('Uploading to ' + name + '...');
}
function uploadFromCloud() {
Images.show.load('top');
CloudCmd.execFromModule('Cloud', 'saveFile', async (currentName, data) => {
const path = DOM.getCurrentDirPath() + currentName;
const [e] = await RESTful.write(path, data);
if (e)
return;
await CloudCmd.refresh({currentName});
});
}
@ -266,15 +269,15 @@ function download(type) {
const PACK = '/pack';
const date = Date.now();
const files = DOM.getActiveFiles();
if (!files.length)
return alertNoFiles();
for (const file of files) {
const selected = DOM.isSelected(file);
const isDir = DOM.isCurrentIsDir(file);
const path = DOM.getCurrentPath(file);
CloudCmd.log('downloading file ' + path + '...');
/*
* if we send ajax request -
@ -283,26 +286,26 @@ function download(type) {
*/
const encodedPath = encodeURI(path).replace(/#/g, '%23');
const id = getIdBySrc(path);
let src;
if (isDir)
src = prefixURL + PACK + encodedPath + DOM.getPackerExt(type);
else
src = prefixURL + FS + encodedPath + '?download';
const element = createElement('iframe', {
id : id + '-' + date,
async: false,
className: 'hidden',
src,
});
const {body} = document;
const removeChild = body.removeChild.bind(body, element);
setTimeout(removeChild, TIME);
if (selected)
DOM.toggleSelectedFile(file);
}
@ -311,12 +314,12 @@ function download(type) {
function getCurrentPosition() {
const current = Info.element;
const rect = current.getBoundingClientRect();
const position = {
x: Math.round(rect.left + rect.width / 3),
y: Math.round(rect.top),
};
return position;
}
@ -325,20 +328,21 @@ function listener(event) {
F9,
ESC,
} = Key;
const key = event.keyCode;
const isBind = Key.isBind();
if (!isBind)
return;
if (key === ESC)
return hide();
if (key === F9) {
const position = getCurrentPosition();
MenuContext.show(position.x, position.y);
event.preventDefault();
}
}

View file

@ -27,11 +27,15 @@ const sourceStore = fullstore();
const Name = 'UserMenu';
CloudCmd[Name] = module.exports;
const {Key} = CloudCmd;
const {
Key,
prefix,
DIR_CLIENT_MODULES,
} = CloudCmd;
module.exports.init = async () => {
await Promise.all([
loadCSS(`${CloudCmd.prefix}/dist/user-menu.css`),
loadCSS(`${prefix}${DIR_CLIENT_MODULES}/user-menu/index.css`),
CloudCmd.View(),
]);
};
@ -43,52 +47,52 @@ const {CurrentInfo} = DOM;
async function show() {
Images.show.load('top');
const {dirPath} = CurrentInfo;
const res = await fetch(`${CloudCmd.prefix}/api/v1/user-menu?dir=${dirPath}`);
const source = await res.text();
const [error, userMenu] = tryCatch(getUserMenu, source);
Images.hide();
if (error)
return Dialog.alert(getCodeFrame({error, source}));
sourceStore(source);
const {
names,
keys,
items,
settings,
} = parseUserMenu(userMenu);
if (settings.run)
return runSelected(settings.select, items, runUserMenu);
const button = createElement('button', {
className: 'cloudcmd-user-menu-button',
innerText: 'User Menu',
notAppend: true,
});
const select = createElement('select', {
className: 'cloudcmd-user-menu',
innerHTML: fillTemplate(names),
notAppend: true,
size: 10,
});
button.addEventListener('click', onButtonClick(userMenu, select));
select.addEventListener('dblclick', onDblClick(userMenu));
select.addEventListener('keydown', onKeyDown({
keys,
userMenu,
}));
const afterShow = () => select.focus();
const autoSize = true;
CloudCmd.View.show([button, select], {
autoSize,
afterShow,
@ -97,10 +101,10 @@ async function show() {
function fillTemplate(options) {
const result = [];
for (const option of options)
result.push(`<option>${option}</option>`);
return result.join('');
}
@ -122,39 +126,39 @@ const onKeyDown = currify(async ({keys, userMenu}, e) => {
keyCode,
target,
} = e;
const keyName = e.key.toUpperCase();
e.preventDefault();
e.stopPropagation();
let value;
if (keyCode === Key.ESC)
return hide();
if (keyCode === Key.ENTER)
value = userMenu[target.value];
else if (keys[keyName])
value = keys[keyName];
else
return navigate(target, e);
await runUserMenu(value);
});
const runUserMenu = async (fn) => {
hide();
const [error] = await tryToCatch(fn, {
DOM,
CloudCmd,
tryToCatch,
});
if (!error)
return;
const source = sourceStore();
return Dialog.alert(getCodeFrame({
error,
@ -164,25 +168,25 @@ const runUserMenu = async (fn) => {
function getCodeFrame({error, source}) {
const {code} = error;
if (!code || code === 'frame')
return error.message;
const [line, column] = parseError(error);
const start = {
line,
column,
};
const location = {
start,
};
const frame = codeFrameColumns(source, location, {
message: error.message,
highlightCode: false,
});
return `<pre>${frame}</pre>`;
}

View file

@ -64,20 +64,20 @@ const Config = {
Images.hide();
Key.unsetBind();
},
beforeClose: () => {
Events.rmKey(listener);
Key.setBind();
},
afterShow: () => {
El.focus();
},
onOverlayClick,
afterClose: noop,
autoSize: false,
helpers: {
title: {},
},
@ -86,62 +86,62 @@ module.exports._Config = Config;
module.exports.init = async () => {
await loadAll();
const events = [
'click',
'contextmenu',
];
events.forEach(addEvent(Overlay, onOverlayClick));
};
async function show(data, options = {}) {
const prefixURL = CloudCmd.prefixURL + FS;
if (Loading)
return;
if (!options || options.bindKeys !== false)
Events.addKey(listener);
El = createElement('div', {
className: 'view',
notAppend: true,
});
El.tabIndex = 0;
if (data) {
if (isArray(data))
El.append(...data);
else
El.append(data);
modal.open(El, initConfig(options));
return;
}
Images.show.load();
const path = prefixURL + Info.path;
const type = options.raw ? '' : await getType(path);
switch(type) {
default:
return await viewFile();
case 'markdown':
return await CloudCmd.Markdown.show(Info.path);
case 'html':
return viewHtml(path);
case 'image':
return viewImage(Info.path, prefixURL);
case 'media':
return await viewMedia(path);
case 'pdf':
return viewPDF(path);
}
@ -154,11 +154,11 @@ function createIframe(src) {
width: '100%',
height: '100%',
});
element.addEventListener('load', () => {
element.contentWindow.addEventListener('keydown', listener);
});
return element;
}
@ -169,21 +169,21 @@ function viewHtml(src) {
function viewPDF(src) {
const element = createIframe(src);
const options = assign({}, Config);
if (CloudCmd.config('showFileName'))
options.title = Info.name;
modal.open(element, options);
}
async function viewMedia(path) {
const [e, element] = await getMediaElement(path);
if (e)
return alert(e);
const allConfig = {
...Config,
...{
@ -195,22 +195,22 @@ async function viewMedia(path) {
},
},
};
modal.open(element, allConfig);
}
async function viewFile() {
const [error, data] = await Info.getData();
if (error)
return Images.hide();
const element = document.createTextNode(data);
const options = Config;
if (CloudCmd.config('showFileName'))
options.title = Info.name;
El.append(element);
modal.open(El, options);
}
@ -220,25 +220,25 @@ const copy = (a) => assign({}, a);
module.exports._initConfig = initConfig;
function initConfig(options) {
const config = copy(Config);
if (!options)
return config;
const names = Object.keys(options);
for (const name of names) {
const isConfig = Boolean(config[name]);
const item = options[name];
if (!isFn(item) || !isConfig) {
config[name] = options[name];
continue;
}
const fn = config[name];
config[name] = series(fn, item);
}
return config;
}
@ -252,14 +252,14 @@ function viewImage(path, prefixURL) {
href: `${prefixURL}${path}`,
title: encode(basename(path)),
});
const names = Info.files
.map(DOM.getCurrentPath)
.filter(isSupportedImage);
const titles = names
.map(makeTitle);
const index = names.indexOf(Info.path);
const imageConfig = {
index,
@ -270,41 +270,41 @@ function viewImage(path, prefixURL) {
title : {},
},
};
const config = {
...Config,
...imageConfig,
};
modal.open(titles, config);
}
async function getMediaElement(src) {
check(src);
const [error, template] = await tryToCatch(Files.get, 'view/media-tmpl');
if (error)
return [error];
const {name} = Info;
if (!TemplateAudio)
TemplateAudio = template;
const is = isAudio(name);
const type = is ? 'audio' : 'video';
const innerHTML = rendy(TemplateAudio, {
src,
type,
name,
});
const element = createElement('div', {
innerHTML,
});
return [null, element];
}
@ -318,12 +318,12 @@ function check(src) {
* @callback - executes, when everything loaded
*/
async function loadAll() {
const {prefix} = CloudCmd;
const {DIRCLIENT_MODULES} = CloudCmd;
time(Name + ' load');
Loading = true;
await loadCSS(`${prefix}/dist/view.css`);
await loadCSS(`${DIRCLIENT_MODULES}view/index.css`);
Loading = false;
}
@ -332,32 +332,32 @@ function onOverlayClick(event) {
x: event.clientX,
y: event.clientY,
};
setCurrentByPosition(position);
}
function setCurrentByPosition(position) {
const element = DOM.getCurrentByPosition(position);
if (!element)
return;
const {
files,
filesPassive,
} = Info;
const isFiles = files.includes(element);
const isFilesPassive = filesPassive.includes(element);
if (!isFiles && !isFilesPassive)
return;
const isCurrent = DOM.isCurrentFile(element);
if (isCurrent)
return;
DOM.setCurrentFile(element);
}

View file

@ -58,7 +58,7 @@
content : '\e80c ';
}
.icon-file::before, {
.icon-file::before {
font-family : 'Fontello';
content : '\e80d ';
}

View file

@ -8,9 +8,9 @@
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link rel="icon" href="{{ prefix }}/favicon.ico">
<link rel=stylesheet href="{{ prefix }}/dist/cloudcmd.css">
<link rel=stylesheet href="{{ prefix }}/dist/client/cloudcmd.css">
<noscript>
<link rel=stylesheet href="{{ prefix }}/dist/nojs.css">
<link rel=stylesheet href="{{ prefix }}/dist/css/nojs.css">
</noscript>
<style data-name="columns">
{{ columns }}
@ -33,8 +33,7 @@
<button id=shift~ class="cmd-button reduce-text icon-terminal" title="Terminal" >⇧ ~</button>
<button id=contact class="cmd-button reduce-text icon-contact" title="Contact" ></button>
</div>
<script src="{{ prefix }}/dist/cloudcmd.common.js"></script>
<script src="{{ prefix }}/dist/cloudcmd.js"></script>
<script src="{{ prefix }}/dist/client/cloudcmd.js"></script>
<script>
CloudCmd({{ config }});
</script>

View file

@ -164,6 +164,7 @@
"css-modules-require-hook": "^4.2.3",
"domtokenlist-shim": "^1.2.0",
"emitify": "^4.0.1",
"esbuild": "^0.17.5",
"eslint": "^8.0.1",
"eslint-plugin-n": "^15.2.4",
"eslint-plugin-putout": "^16.0.0",

View file

@ -36,7 +36,7 @@ const fileop = require('@cloudcmd/fileop');
const DIR_ROOT = DIR + '../';
const isDev = process.env.NODE_ENV === 'development';
const getDist = (isDev) => isDev ? 'dist-dev' : 'dist';
const getDist = () => 'html';//(isDev) => isDev ? 'dist-dev' : 'dist';
const getIndexPath = (isDev) => path.join(DIR, '..', `${getDist(isDev)}/index.html`);
const html = fs.readFileSync(getIndexPath(isDev), 'utf8');

View file

@ -15,7 +15,7 @@ const isDev = process.env.NODE_ENV === 'development';
const getDist = (isDev) => isDev ? 'dist-dev' : 'dist';
const dist = getDist(isDev);
const columnsDir = path.join(__dirname, '..', dist, 'columns');
const columnsDir = path.join(__dirname, '..', 'dist', 'css', 'columns');
const names = fs.readdirSync(columnsDir)
.filter(not(isMap));