• Эффективность работы верстальщиков - как реализовать удобный live reload при работе с PerfectPixel?

    @zverygi
    Немного знаю html
    ну если используется галп или подобное(что априори должно быть) то есть "пиксель глас". И никаких браузерных расширений
    статься на анг
    https://yoksel.github.io/pixel-glass-js/
    статья на рус
    css.yoksel.ru/adaptive-pixel-perfect
    Ответ написан
    Комментировать
  • Как автоматически создавать пустые файлы внутри созданной папки?

    @zverygi
    Немного знаю html
    отдельный скрипт для запуска через npm, код ниже создает папку и три файла .pug, .sass, .js. Все это дело ложим в корень в файл .js, ну и правим путь к общей папки где будут лежать модули в этой строке "const BLOCKS_DIR = path.join(__dirname, 'dev/pug/modules');"

    // создание блока набрать node block you_block_name
    'use strict';
    
    const fs = require('fs')
    const path = require('path')
    const colors = require('colors')
    const readline = require('readline')
    
    const rl = readline.createInterface(process.stdin, process.stdout);
    
    // folder with all blocks
    const BLOCKS_DIR = path.join(__dirname, 'dev/pug/modules');
    
    //////////////////////////////////////////////////////////////////////////////////////////////////
    
    // default content for files in new block
    const fileSources = {
    	pug : `mixin {blockName}()\n\t.{blockName}\n\t\t| {blockName}\n`,
    	sass: `/*! {blockName} style */ \n` //можно задать изначальные значения/текст
    //	js	: `// .{blockName} scripts goes here`
    };
    
    function validateBlockName(blockName) {
    	return new Promise((resolve, reject) => {
    		const isValid = /^(\d|\w|-)+$/.test(blockName);
    
    		if (isValid) {
    			resolve(isValid);
    		} else {
    			const errMsg = (
    				`ERR>>> An incorrect block name '${blockName}'\n` +
    				`ERR>>> A block name must include letters, numbers & the minus symbol.`
    			);
    			reject(errMsg);
    		}
    	});
    }
    
    function directoryExist(blockPath, blockName) {
    	return new Promise((resolve, reject) => {
    		fs.stat(blockPath, notExist => {
    			if (notExist) {
    				resolve();
    			} else {
    				reject(`ERR>>> The block '${blockName}' already exists.`.red);
    			}
    		});
    	});
    }
    
    function createDir(dirPath) {
    	return new Promise((resolve, reject) => {
    		fs.mkdir(dirPath, err => {
    			if (err) {
    				reject(`ERR>>> Failed to create a folder '${dirPath}'`.red);
    			} else {
    				resolve();
    			}
    		});
    	});
    }
    
    function createFiles(blocksPath, blockName) {
    	const promises = [];
    	Object.keys(fileSources).forEach(ext => {
    		const fileSource = fileSources[ext].replace(/\{blockName}/g, blockName);
    		const filename = `${blockName}.${ext}`;
    		const filePath = path.join(blocksPath, filename);
    
    		promises.push(
    				new Promise((resolve, reject) => {
    					fs.writeFile(filePath, fileSource, 'utf8', err => {
    						if (err) {
    							reject(`ERR>>> Failed to create a file '${filePath}'`.red);
    						} else {
    							resolve();
    						}
    					});
    				})
    		);
    	});
    
    	return Promise.all(promises);
    }
    
    function getFiles(blockPath) {
    	return new Promise((resolve, reject) => {
    		fs.readdir(blockPath, (err, files) => {
    			if (err) {
    				reject(`ERR>>> Failed to get a file list from a folder '${blockPath}'`);
    			} else {
    				resolve(files);
    			}
    		});
    	});
    }
    
    function printErrorMessage(errText) {
    	console.log(errText);
    	rl.close();
    }
    
    // //////////////////////////////////////////////////////////////////////////
    
    function initMakeBlock(blockName) {
    	const blockPath = path.join(BLOCKS_DIR, blockName);
    
    	return validateBlockName(blockName)
    		.then(() => directoryExist(blockPath, blockName))
    		.then(() => createDir(blockPath))
    		.then(() => createFiles(blockPath, blockName))
    		.then(() => getFiles(blockPath))
    		.then(files => {
    			const line = '-'.repeat(48 + blockName.length);
    			console.log(line);
    			console.log(`The block has just been created in 'source/blocks/${blockName}'`);
    			console.log(line);
    
    			// Displays a list of files created
    			files.forEach(file => console.log(file.yellow));
    
    			rl.close();
    		});
    }
    
    
    // //////////////////////////////////////////////////////////////////////////
    //
    // Start here
    //
    
    // Command line arguments
    const blockNameFromCli = process.argv
    		.slice(2)
    		// join all arguments to one string (to simplify the capture user input errors)
    		.join(' ');
    
    
    // If the user pass the name of the block in the command-line options
    // that create a block. Otherwise - activates interactive mode
    if (blockNameFromCli !== '') {
    	initMakeBlock(blockNameFromCli).catch(printErrorMessage);
    }
    else {
    	rl.setPrompt('Block name: '.magenta);
    	rl.prompt();
    	rl.on('line', (line) => {
    		const blockName = line.trim();
    		initMakeBlock(blockName).catch(printErrorMessage);
    	});
    }
    Ответ написан
  • Как защитить свою работу фрилансеру?

    @zverygi
    Немного знаю html
    полностью никак, усложнить это да
    закрывайте меню через пкм, закрывайте вызов консоли через сочетание клавиш( но если через меню браузера то все равно откроется ), блочить выкачку через "вегет" и ему подобных
    можно еще плагинами под галп и ему подобных сделать "машинные" название классов
    Ответ написан
    Комментировать
  • Почему gulp.spritesmith не генерирует stylus-код для retina-спрайта?

    @zverygi
    Немного знаю html
    в первом варианте не нужно указывать тип файла на выходе,
    cssFormat: 'stylus',
    без нее таск будет работать, плюс нужно добавить
    @include retina-sprites($retina-groups)
    туда где "собираются" стили
    Ответ написан
    Комментировать