mollenhauer
/
setup.js
487 строк · 13.6 Кб
1import fs from 'fs-extra'2import replace from 'replace-in-file'3import { log } from 'console'4import enquirer from 'enquirer'5import chalk from 'chalk'6
7class ModuleObject {8constructor(config = {}) {9this.moduleName = null10this.filesAndFolders = null11this.htmlConnectStrings = null12
13Object.assign(this, config)14}15}
16class VariableTemplate {17constructor(config = {}) {18this.fields = null19this.message = null20this.template = null21this.snippetName = null22this.variableFilePath = null23
24Object.assign(this, config)25}26}
27
28const pathToProject = './',29distFolderName = pathToProject + 'dist/',30snippetsFolderName = pathToProject + 'snippets/',31readmeFolder = pathToProject + 'readmeFiles/',32sources = pathToProject + 'sources/',33readmeFilePath = pathToProject + 'README.md',34scriptsFolder = sources + 'scripts/',35stylesFolder = sources + 'styles/',36componentsFolder = sources + 'components/',37assets = sources + 'assets/',38environmentFilePath = stylesFolder + '_environment.pcss',39baseStyleFile = stylesFolder + 'normalize.pcss',40stateStyleFile = stylesFolder + 'thirdLevelRules.pcss',41layoutHtmlFile = componentsFolder + 'layout.html',42fontsGitkeep = sources + 'fonts/.gitkeep',43indexPage = sources + 'index.html'44
45
46logSomeImportantInConsole(47`Salute!48You will have to use some keys, such as:
49${chalk.greenBright('↑')} - focus up,50${chalk.greenBright('↓')} - focus down,51${chalk.greenBright('← →')} - choosing between elements on the same line,52${chalk.greenBright('space')} - to select an option,53${chalk.greenBright('⭾')} - tab, to move to a next element, for example, in templates.54`,55chalk.green56)
57
58await enquirer.toggle({59message: chalk.italic('Any questions?'),60enabled: chalk.magenta('Nope, i totally understand!'),61disabled: chalk.magenta('Nope, i understand!'),62})63
64
65await includeModuleByQuestion(66'Whether you want to save the plugin...',67
68new ModuleObject({69moduleName: 'Just Validate',70filesAndFolders: assets + 'justValidate/',71htmlConnectStrings: { strings: `justValidate=false` },72}),73new ModuleObject({74moduleName: 'Slider Swiper',75filesAndFolders: assets + 'swiper/',76htmlConnectStrings: { strings: `swiper=false` },77}),78new ModuleObject({79moduleName: 'Typed',80filesAndFolders: assets + 'typed/',81htmlConnectStrings: { strings: `typed=false` },82}),83new ModuleObject({84moduleName: 'Input Mask',85filesAndFolders: assets + 'inputmask.min.js',86}),87new ModuleObject({88moduleName: 'Photo Swipe',89filesAndFolders: assets + 'photoswipe/',90htmlConnectStrings: { strings: `photoSwipe=false` },91}),92new ModuleObject({93moduleName: 'No Ui Slider',94filesAndFolders: assets + 'nouislider/',95htmlConnectStrings: { strings: `noUiSlider=false` },96})97)
98await includeModuleByQuestion(99'Whether you want to save the module...',100
101new ModuleObject({102moduleName: 'Scripts for dialog',103filesAndFolders: [104scriptsFolder + 'dialogs/',105componentsFolder + 'modals.html',106],107htmlConnectStrings: [108{ strings: `<x-modals></x-modals>`, },109{ strings: `dialogs=false` },110],111}),112new ModuleObject({113moduleName: 'Tabs',114filesAndFolders: scriptsFolder + 'tab/',115htmlConnectStrings: [116{ strings: `tabs=false` }117],118}),119new ModuleObject({120moduleName: 'Parallax by mouse',121filesAndFolders: scriptsFolder + 'mouseParallax/',122htmlConnectStrings: [123{ strings: `mouseParallax=false` }124],125}),126new ModuleObject({127moduleName: 'AutoScrollPadding',128filesAndFolders: scriptsFolder + 'autoScrollPadding/',129htmlConnectStrings: [130{ strings: `autoScrollPadding=false` }131],132}),133new ModuleObject({134moduleName: 'Tools for observer',135filesAndFolders: scriptsFolder + 'observerTools/',136htmlConnectStrings: [137{ strings: `observerTools=false` }138],139}),140new ModuleObject({141moduleName: 'Horizontal scroll by mouse wheel',142filesAndFolders: scriptsFolder + 'horizontalMouseScroll.ts',143htmlConnectStrings: [144{ strings: `horizontalMouseScroll=false` }145],146}),147new ModuleObject({148moduleName: 'Switching by swipe',149filesAndFolders: scriptsFolder + 'toggleBySwipe/',150htmlConnectStrings: [151{ strings: `toggleBySwipe=false` }152],153}),154new ModuleObject({155moduleName: 'Step By Step block',156filesAndFolders: scriptsFolder + 'stepByStepBlock/',157htmlConnectStrings: [158{ strings: `stepByStep=false` }159],160}),161new ModuleObject({162moduleName: 'scroll-timeline polyfill',163filesAndFolders: scriptsFolder + 'scroll-timeline.js',164htmlConnectStrings: [165{ strings: `scrollTimeline=false` }166],167}),168new ModuleObject({169moduleName: 'Infinite auto-scroll',170filesAndFolders: scriptsFolder + 'infiniteScroll/',171htmlConnectStrings: [172{ strings: `infiniteScroll=false` }173],174}),175)
176
177
178logSomeImportantInConsole(179`\nThe configuration of files and folders is complete.\n`,180chalk.greenBright181)
182logSomeImportantInConsole(183`\nNow, i suggest you change the values of the main variables.\n`,184chalk.magentaBright185)
186
187await setVariables(188new VariableTemplate({189snippetName: 'htmlLayout',190message: chalk.cyanBright('Fill in the fields in the html-layout.'),191variableFilePath: layoutHtmlFile,192fields: [193{ name: 'mainLangOfPages', initial: 'en' },194{ name: 'preloadedFontFilename', initial: 'none', },195],196template:197`// Set the main language of pages below.198lang: '\${mainLangOfPages}',
199// Set a name for a preloaded font. Must be a file name without extension.
200preloadedFontName: '\${preloadedFontFilename}',`201}),202
203new VariableTemplate({204snippetName: 'Title of index page',205message: chalk.cyanBright('Title of index page...'),206variableFilePath: indexPage,207fields: [208{ name: 'title', initial: 'Unnamed Page' },209],210template:211`<x-layout title='\${title}'`212}),213
214new VariableTemplate({215snippetName: 'stylesheetVariables',216message: chalk.cyanBright(217`Fill in some css variables (file - ${chalk.underline(baseStyleFile)}).`),218variableFilePath: baseStyleFile,219fields: [220{ name: 'mainFontName', initial: 'arial', },221{ name: 'mainTextColor', initial: 'black', },222{ name: 'backgroundColor', initial: 'white', },223],224template:225`--main-font-family: \${mainFontName};226--main-text-color: \${mainTextColor};
227--background: \${backgroundColor};`228}),229
230new VariableTemplate({231snippetName: 'stylesheetSassLikeVariables',232message: chalk.cyanBright(233'Fill in sass-like variables that are used in custom media. \n'234+ `(file - ${chalk.underline(environmentFilePath)})`),235variableFilePath: environmentFilePath,236fields: [237{ name: 'widthOfYourDesignLayout', initial: '1440', },238{ name: 'minimalWidthOfYourDesign', initial: '320', },239{ name: 'mainSize', initial: '16', },240{ name: 'minSize', initial: '12', },241],242template:243`@custom-media --is-large-layout (width > $layoutWidth);244@custom-media --is-layout-width (769px <= width <= $layoutWidth);
245@custom-media --is-tablet (426px <= width <= 769px);
246@custom-media --is-mobile (width <= 426px);
247
248$layoutWidth: \${widthOfYourDesignLayout}px;
249$minLayoutWidth: \${minimalWidthOfYourDesign}px;
250$mainFontSize: \${mainSize}px;
251$minFontSize: \${minSize}px;`252}),253
254new VariableTemplate({255snippetName: 'some name',256message: chalk.cyanBright(257'Set the values of the paddings that are assigned using the .content_paddings class (used to center content in blocks)\n'258+ `(file - ${chalk.underline(stateStyleFile)}.`),259variableFilePath: stateStyleFile,260fields: [261{ name: 'largePaddings', initial: '15vw', },262],263template:264`265@media (--is-large-layout) {
266--content-inline-padding: \${largePaddings};
267}`,268}),269
270new VariableTemplate({271snippetName: 'some name 2',272message: chalk.cyan('Layout width...'),273variableFilePath: stateStyleFile,274fields: [275{ name: 'defaultPaddings', initial: '10vw', },276],277template:278`279@media (--is-layout-width) {
280--content-inline-padding: \${defaultPaddings};
281}`,282}),283
284new VariableTemplate({285snippetName: 'some name 3',286message: chalk.cyan('Tablets...'),287variableFilePath: stateStyleFile,288fields: [289{ name: 'tabletPaddings', initial: '5vw', },290],291template:292`293@media (--is-tablet) {
294--content-inline-padding: \${tabletPaddings};
295}`,296}),297
298new VariableTemplate({299snippetName: 'some name 4',300message: chalk.cyan('Mobiles...'),301variableFilePath: stateStyleFile,302fields: [303{ name: 'mobilePaddings', initial: '2.5vw', },304],305template:306`307@media (--is-mobile) {
308--content-inline-padding: \${mobilePaddings};
309}`,310}),311)
312
313deleteUnnecessaryFilesAndFolders()314
315
316writeCompletelyPhrase()317
318
319async function includeModuleByQuestion(title, ...moduleObjects) {320let selectedModules = await enquirer.multiselect({321name: 'value',322message: chalk.magentaBright(title),323limit: 5,324choices: moduleObjects.map(module => {325return {326name: module.moduleName, value: module.moduleName,327}328}),329
330footer: () => chalk.gray.italic('use ↑ and ↓ to switch, you can "scroll" this list')331})332
333
334for (let module of moduleObjects) {335let confirmedModuleName = selectedModules.find(answer => answer == module.moduleName)336
337if (confirmedModuleName) {338replaceHtmlConnectionString(module.htmlConnectStrings, 'false', 'true')339continue340}341
342if (!Array.isArray(module.filesAndFolders))343module.filesAndFolders = new Array(module.filesAndFolders)344
345for (let fileOrFolder of module.filesAndFolders) {346fs.removeSync(fileOrFolder)347}348
349replaceHtmlConnectionString(module.htmlConnectStrings)350}351}
352async function setVariables(...variableTemplates) {353for (let variableTemplate of variableTemplates) {354let result = await enquirer.snippet({355name: variableTemplate.snippetName,356message: variableTemplate.message + '\n',357required: true,358fields: variableTemplate.fields,359template: variableTemplate.template,360
361footer: () => chalk.gray.italic("use tab to move, when you're done, press enter")362})363
364let formattedTemplate = replaceEnquirerTemplateValues(365variableTemplate.template,366variableTemplate.fields,367result.values,368true369)370let newTemplate = replaceEnquirerTemplateValues(371variableTemplate.template,372variableTemplate.fields,373result.values374)375
376let templateStrings = formattedTemplate.split('\n')377let newTemplateStrings = newTemplate.split('\n')378
379for (let i = 0; i < templateStrings.length; i++) {380await replace({381files: variableTemplate.variableFilePath,382from: templateStrings[i],383to: newTemplateStrings[i],384})385}386}387}
388
389function deleteUnnecessaryFilesAndFolders() {390deleteFolder(readmeFolder, 'The readme folder have been deleted.')391deleteFolder(readmeFilePath)392fs.createFileSync('README.md')393
394log(chalk.gray.italic('✅ The readme file are clean.'))395
396deleteFolder(distFolderName, 'Dist have been deleted.')397deleteFolder(snippetsFolderName, 'Snippets have been deleted.')398deleteFolder(fontsGitkeep, 'Gitkeep in fonts have been deleted.')399}
400
401function replaceHtmlConnectionString(htmlConnectStrings, replacedValue, replacedNewValue) {402if (!htmlConnectStrings) return403
404if (!Array.isArray(htmlConnectStrings))405htmlConnectStrings = new Array(htmlConnectStrings)406
407for (let htmlConnectStringData of htmlConnectStrings) {408if (!htmlConnectStringData.path)409htmlConnectStringData.path = indexPage410
411let newHtmlConnectString412
413if (!replacedValue || !replacedNewValue) {414newHtmlConnectString = ''415} else {416newHtmlConnectString = htmlConnectStringData.strings.replace(replacedValue, replacedNewValue)417}418
419replace.sync({420files: htmlConnectStringData.path,421from: htmlConnectStringData.strings, to: newHtmlConnectString,422})423}424}
425function deleteFolder(folderPath, messageOnSuccessful) {426try {427fs.removeSync(folderPath)428
429if (messageOnSuccessful)430log(chalk.gray.italic('✅ ' + messageOnSuccessful))431}432catch (error) {433log(chalk.red('❌ ' + error))434}435}
436function replaceEnquirerTemplateValues(template, fields, values, replaceNamesToDefaults) {437let newTemplate = template438
439if (replaceNamesToDefaults) {440for (let field of fields) {441newTemplate = newTemplate.replaceAll(442'${' + field.name + '}',443field.initial ?? ''444)445}446}447else {448for (let field of fields) {449newTemplate = newTemplate.replaceAll(450'${' + field.name + '}',451values[field.name] ?? field.initial452)453}454}455
456return newTemplate457}
458function logSomeImportantInConsole(message, chalkColor) {459log(chalkColor(message))460}
461
462function writeCompletelyPhrase() {463let464topPhrase = 'The setup is completely complete!',465middlePhrase = 'I wish You a successful job.',466bottomPhrase = '🎆🎆🎆',467
468positionOfTop = Math.round(process.stdout.columns / 2) - Math.round(topPhrase.length / 2),469positionOfMiddle = Math.round(process.stdout.columns / 2) - Math.round(middlePhrase.length / 2),470positionOfBottom = Math.round(process.stdout.columns / 2) - Math.round(bottomPhrase.length / 2)471
472topPhrase = ' '.repeat(positionOfTop) + topPhrase473middlePhrase = ' '.repeat(positionOfMiddle) + middlePhrase474bottomPhrase = ' '.repeat(positionOfBottom) + bottomPhrase475
476logSomeImportantInConsole(477'\n'478+ topPhrase + '\n'479+ middlePhrase + '\n'480+ bottomPhrase + '\n'481
482, chalk.greenBright483)484
485// An empty line to correct one error in the visualization486console.log('')487}