├── app ├── templates │ ├── base │ │ ├── gitkeep │ │ ├── editorconfig │ │ ├── tern-project.json.ejs │ │ ├── LICENSE │ │ ├── package.json.ejs │ │ ├── webpack.config.js │ │ └── README.md.ejs │ ├── styles │ │ ├── main │ │ │ ├── _mixins.scss │ │ │ ├── _variables.scss │ │ │ ├── screens │ │ │ │ ├── _base.scss │ │ │ │ └── _screen.scss │ │ │ ├── components │ │ │ │ ├── _forms.scss │ │ │ │ └── _buttons.scss │ │ │ └── main.scss │ │ └── vendor │ │ │ ├── vendor.scss │ │ │ └── _reset.scss │ ├── git │ │ ├── gitattributes │ │ └── gitignore │ ├── webpack │ │ ├── developmentPlugins.js │ │ ├── debugPlugins.js │ │ ├── paths.js │ │ ├── productionPlugins.js │ │ └── commonPlugins.js │ ├── markup │ │ ├── pug │ │ │ ├── layouts │ │ │ │ ├── general │ │ │ │ │ ├── footer.pug │ │ │ │ │ └── menu.pug │ │ │ │ ├── includes │ │ │ │ │ └── mixins.pug │ │ │ │ └── layout-primary.pug.ejs │ │ │ └── _screen.pug │ │ └── _screen.html.ejs │ ├── assets │ │ ├── head │ │ │ ├── favico.ico │ │ │ ├── favicon.png │ │ │ └── manifest.json.ejs │ │ ├── images │ │ │ └── logo.png │ │ └── icons │ │ │ └── react.svg │ ├── gulp │ │ ├── common │ │ │ ├── fonts.js │ │ │ ├── cssModulesWrite.js │ │ │ ├── scripts.js │ │ │ ├── static.js.ejs │ │ │ ├── styles.js │ │ │ └── markup.js.ejs │ │ ├── production │ │ │ ├── purify.js │ │ │ ├── minifyStyles.js │ │ │ ├── zip.js │ │ │ └── styles-production.js │ │ ├── development │ │ │ ├── serve.js │ │ │ └── watch.js.ejs │ │ ├── gulpfile.js.ejs │ │ └── config.js.ejs │ └── scripts │ │ ├── index.js.ejs │ │ ├── framework.js.ejs │ │ └── app.js ├── filesToAssert.js └── index.js ├── .gitattributes ├── .gitlab-ci.yml ├── .gitignore ├── .travis.yml ├── .babelrc ├── .editorconfig ├── test ├── jquery.js ├── scripts.js ├── foundation.js ├── general.js ├── scss.js ├── bootstrap.js └── markup.js ├── LICENSE ├── docs └── running_the_generator.md ├── package.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md └── README.md /app/templates/base/gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /app/templates/styles/main/_mixins.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/templates/styles/main/_variables.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/templates/git/gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /app/templates/styles/main/screens/_base.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/templates/webpack/developmentPlugins.js: -------------------------------------------------------------------------------- 1 | module.exports = [] 2 | -------------------------------------------------------------------------------- /app/templates/markup/pug/layouts/general/footer.pug: -------------------------------------------------------------------------------- 1 | //- Replace this with the footer 2 | -------------------------------------------------------------------------------- /app/templates/markup/pug/layouts/general/menu.pug: -------------------------------------------------------------------------------- 1 | //- replace this for a menu :) 2 | -------------------------------------------------------------------------------- /app/templates/styles/main/screens/_screen.scss: -------------------------------------------------------------------------------- 1 | // 2 | // <%=projectName%> 3 | // Screen <%= screenNumber %> 4 | // 5 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | test: 2 | image: pixel2html/node-npm-cache:8 3 | script: 4 | - npm install 5 | - npm test 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | bower_components 5 | demo 6 | test/temp 7 | yarn.lock 8 | package-lock.json 9 | -------------------------------------------------------------------------------- /app/templates/assets/head/favico.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/pixel2html-generator/HEAD/app/templates/assets/head/favico.ico -------------------------------------------------------------------------------- /app/templates/assets/head/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/pixel2html-generator/HEAD/app/templates/assets/head/favicon.png -------------------------------------------------------------------------------- /app/templates/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/pixel2html-generator/HEAD/app/templates/assets/images/logo.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | node_js: 5 | - "6.9.0" 6 | 7 | cache: 8 | directories: 9 | - node_modules 10 | -------------------------------------------------------------------------------- /app/templates/assets/head/manifest.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "<%= projectName %>", 3 | "name": "<%= projectName %>", 4 | "start_url": "index.html" 5 | } 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", 4 | { 5 | "targets": { 6 | "node": 6, 7 | "uglify": 2 8 | } 9 | }] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /app/templates/webpack/debugPlugins.js: -------------------------------------------------------------------------------- 1 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 2 | 3 | const debugPlugins = [ 4 | new BundleAnalyzerPlugin() 5 | ] 6 | 7 | module.exports = debugPlugins 8 | -------------------------------------------------------------------------------- /app/templates/styles/main/components/_forms.scss: -------------------------------------------------------------------------------- 1 | input[type="text"], 2 | input[type="email"], 3 | input[type="url"], 4 | input[type="password"], 5 | input[type="search"], 6 | textarea { 7 | 8 | &:focus { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/templates/gulp/common/fonts.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | 4 | gulp.task('fonts', () => 5 | gulp.src(config.project.fontFiles) 6 | .pipe(gulp.dest(config.directories.dist.fonts)) 7 | ) 8 | -------------------------------------------------------------------------------- /app/templates/styles/main/components/_buttons.scss: -------------------------------------------------------------------------------- 1 | button, 2 | input[type="button"], 3 | input[type="reset"], 4 | input[type="submit"] { 5 | 6 | &:hover { 7 | 8 | } 9 | 10 | &:active, 11 | &:focus { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /app/templates/base/editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /app/templates/scripts/index.js.ejs: -------------------------------------------------------------------------------- 1 | <% if (frontEndFramework) { -%> 2 | // Start frontEndFramework 3 | import './framework' 4 | <% } -%> 5 | 6 | // Here we are importing the whole app 7 | // read more about modules here: 8 | // http://wesbos.com/javascript-modules/ 9 | import './app' 10 | -------------------------------------------------------------------------------- /app/templates/markup/pug/_screen.pug: -------------------------------------------------------------------------------- 1 | extends layouts/layout-primary 2 | 3 | block content 4 | section.delete-all-of-this-to-begin 5 | h1 <%= projectName %> - Screen <%= screenNumber %> 6 | p Welcome to our lovely Pixel2Html Generator. 7 | p Please go ahead and remove this from the partial file and go and hack along 8 | -------------------------------------------------------------------------------- /app/templates/gulp/common/cssModulesWrite.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | const fs = require('fs-path') 4 | const getJSON = require('@pixel2html/pipes').getJSON 5 | 6 | gulp.task('writeModules', done => { 7 | const json = getJSON() 8 | fs.writeFileSync(config.directories.src.cssModules, json) 9 | done() 10 | }) 11 | -------------------------------------------------------------------------------- /app/templates/gulp/production/purify.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | const purify = require('@pixel2html/pipes').purify 4 | 5 | gulp.task('purify', () => 6 | gulp.src(config.directories.dist.styles + '*.css') 7 | .pipe(purify({paths: config.purify})()) 8 | .pipe(gulp.dest(config.directories.dist.styles)) 9 | ) 10 | -------------------------------------------------------------------------------- /app/templates/gulp/production/minifyStyles.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const minifyStyles = require('@pixel2html/pipes').minifyStyles 3 | const config = require('../config') 4 | 5 | gulp.task('minifyStyles', () => 6 | gulp.src(config.directories.dist.styles + '/*.css') 7 | .pipe(minifyStyles()()) 8 | .pipe(gulp.dest(config.directories.dist.styles)) 9 | ) 10 | -------------------------------------------------------------------------------- /app/templates/webpack/paths.js: -------------------------------------------------------------------------------- 1 | const {cwd} = require('process') 2 | const {join} = require('path') 3 | const config = require('../gulp/config') 4 | 5 | const c = cwd() 6 | 7 | module.exports = { 8 | src: join(c, config.directories.src.base), 9 | entry: join(c, config.project.jsMainFile), 10 | output: join(c, config.directories.dist.scripts), 11 | styles: join(c, config.directories.src.cssModules) 12 | } 13 | -------------------------------------------------------------------------------- /app/templates/gulp/common/scripts.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const webpack = require('webpack') 3 | const webpackConfig = require('../../webpack.config') 4 | 5 | gulp.task('scripts', () => 6 | new Promise(resolve => webpack(webpackConfig, (err, stats) => { 7 | if (err) console.log('Webpack', err) 8 | console.log(stats.toString({ 9 | chunks: false, 10 | colors: true 11 | })) 12 | resolve() 13 | })) 14 | ) 15 | -------------------------------------------------------------------------------- /app/templates/scripts/framework.js.ejs: -------------------------------------------------------------------------------- 1 | <% if (frontEndFramework === 'bootstrap-4') { -%> 2 | // Start Bootstrap 4 3 | import 'bootstrap' 4 | <% } -%> 5 | <% if (frontEndFramework === 'bootstrap-3') { -%> 6 | // Start Bootstrap 3 7 | require('bootstrap-sass') 8 | <% } -%> 9 | <% if (frontEndFramework === 'foundation') { -%> 10 | // Start foundation 11 | import $ from 'jquery' 12 | import 'foundation-sites' 13 | $(document).foundation() 14 | <% } -%> 15 | -------------------------------------------------------------------------------- /app/templates/gulp/production/zip.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | const zip = require('gulp-zip') 4 | 5 | gulp.task('zip', () => { 6 | const distFiles = [ 7 | `${config.directories.dist.base}/**`, 8 | `!${config.directories.dist.base}` 9 | ] 10 | 11 | return gulp.src(distFiles, {base: '.'}) 12 | .pipe(zip('latest.zip')).on('error', config.onError) 13 | .pipe(gulp.dest('dist/releases')) 14 | }) 15 | -------------------------------------------------------------------------------- /app/templates/webpack/productionPlugins.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin') 3 | 4 | const productionPlugins = [ 5 | new webpack.optimize.ModuleConcatenationPlugin(), 6 | new webpack.DefinePlugin({ 7 | 'process.env': { 8 | 'NODE_ENV': JSON.stringify('production') 9 | } 10 | }), 11 | new UglifyJSPlugin({sourceMap: true}) 12 | ] 13 | 14 | module.exports = productionPlugins 15 | -------------------------------------------------------------------------------- /app/templates/markup/pug/layouts/includes/mixins.pug: -------------------------------------------------------------------------------- 1 | //- In honor of loved hyperscript daddy of React and Friends 2 | //- https://github.com/hyperhype/hyperscript 3 | mixin h(htmlElement, module) 4 | #{htmlElement}(css-module=module) 5 | if block 6 | block 7 | 8 | //- Thanks WesBos! 9 | mixin svg(filename) 10 | !=icon(filename) 11 | 12 | mixin img(name, module, alt) 13 | img(src=`assets/images/${name}` css-module=module alt= alt ? alt : 'An image') 14 | -------------------------------------------------------------------------------- /app/templates/styles/vendor/vendor.scss: -------------------------------------------------------------------------------- 1 | // 2 | // <%=projectName%> 3 | // 4 | <% if(frontEndFramework === 'bootstrap-4'){ %> 5 | @import "bootstrap/scss/bootstrap.scss"; 6 | <% } %> 7 | <% if(frontEndFramework === 'bootstrap-3'){ %> 8 | @import "bootstrap-sass"; 9 | <% } %> 10 | <% if(frontEndFramework === 'foundation'){ %> 11 | @import "foundation-sites/scss/foundation"; 12 | @include foundation-everything; 13 | <% } %> 14 | <% if(!frontEndFramework){ %> 15 | @import "reset"; 16 | <% } %> 17 | -------------------------------------------------------------------------------- /app/templates/git/gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | bower_components 5 | node_modules 6 | 7 | # Ignore CSS Modules JSON files 8 | src/assets/cssModules 9 | 10 | _gh_pages 11 | _site 12 | *.diff 13 | *.err 14 | *.orig 15 | *.log 16 | *.rej 17 | *.swo 18 | *.swp 19 | *.zip 20 | *.vi 21 | *~ 22 | .DS_Store 23 | ._* 24 | Thumbs.db 25 | .cache 26 | .project 27 | .settings 28 | .tmproj 29 | *.esproj 30 | nbproject 31 | *.sublime-project 32 | *.sublime-workspace 33 | .idea 34 | .sass-cache 35 | .tmp 36 | iTermocil.yml 37 | .tmuxinator 38 | 39 | /releases/* 40 | -------------------------------------------------------------------------------- /app/templates/styles/main/main.scss: -------------------------------------------------------------------------------- 1 | // 2 | // <%=projectName%> 3 | // 4 | @import 'variables'; 5 | @import 'mixins'; 6 | 7 | // We can use CSS modules 8 | // but for now its disabled 9 | // make sure your css is inside this :global 10 | // Happy Styling! Pixel2HTML 11 | :global { 12 | // screens:start 13 | @import 'screens/_base'; 14 | <% for(var i=1; i<=qtyScreens; i++) {%> 15 | @import 'screens/screen_<%=i%>';<% } %> 16 | // screens:end 17 | 18 | // components:start 19 | @import 'components/_forms'; 20 | @import 'components/_buttons'; 21 | // components:end 22 | } 23 | -------------------------------------------------------------------------------- /app/templates/scripts/app.js: -------------------------------------------------------------------------------- 1 | // Welcome to our main file! 2 | // we are using Webpack and ES6 3 | // feel free to use imports and exports 4 | // as well as ES6 code 5 | 6 | // Try to make your whole code work via exporting 7 | // a single function to get Hot Module Replacement 8 | // just like app.init() 9 | // from the good ol'days 10 | 11 | const colors = [ 'pink', 'red', 'blue' ] 12 | const moColors = ['yellow', 'papayawhip'] 13 | 14 | const allTheColors = [ ...colors, ...moColors ] 15 | allTheColors.map(color => console.log(`The color is ${color}`)) 16 | 17 | // Happy coding from Pixel2HTML 18 | -------------------------------------------------------------------------------- /app/templates/base/tern-project.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaVersion": 6, 3 | "libs": [ 4 | "browser" 5 | <% if(jQuery || frontEndFramework){ -%> 6 | ,"jquery" 7 | <% } -%> 8 | ], 9 | "loadEagerly": [], 10 | "dontLoad": [ 11 | "node_modules/**" 12 | ], 13 | "plugins": { 14 | "doc_comment": true, 15 | "node": { 16 | "dontLoad": "", 17 | "load": "", 18 | "modules": "" 19 | }, 20 | "node_resolve": {}, 21 | "es_modules": {}, 22 | "modules": { 23 | "dontLoad": "", 24 | "load": "", 25 | "modules": "" 26 | }, 27 | "commonjs": {} 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/templates/webpack/commonPlugins.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | 3 | let common = [ 4 | // Split vendor packages coming from npm 5 | new webpack.optimize.CommonsChunkPlugin({ 6 | name: 'vendor', 7 | minChunks: module => /node_modules/.test(module.resource) 8 | }), 9 | // Allow everyone to use jQuery like it was global 10 | new webpack.ProvidePlugin({ 11 | $: 'jquery', 12 | jQuery: 'jquery', 13 | 'window.jQuery': 'jquery', 14 | // Popper is for Bootstrap 4 mainly 15 | Popper: ['popper.js', 'default'] 16 | }), 17 | // Do NOT import the BLOAT from moment.js 18 | // thanks create-react-app 19 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) 20 | ] 21 | 22 | module.exports = common 23 | -------------------------------------------------------------------------------- /app/templates/gulp/common/static.js.ejs: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | const del = require('del') 4 | 5 | gulp.task('clean', () => 6 | del([ 7 | config.directories.dist.base, 8 | config.directories.src.cssModules 9 | ]) 10 | ) 11 | 12 | gulp.task('images', () => 13 | gulp.src(config.directories.src.images + '/**/*') 14 | .pipe(gulp.dest(config.directories.dist.images)) 15 | ) 16 | <% if(markupLanguage === 'html'){ -%> 17 | gulp.task('icons', () => 18 | gulp.src(config.directories.src.icons + '/**/*') 19 | .pipe(gulp.dest(config.directories.dist.icons)) 20 | )<% } -%> 21 | 22 | gulp.task('head', () => 23 | gulp.src(config.directories.src.base + '/assets/head/**/*') 24 | .pipe(gulp.dest(config.directories.dist.base + '/assets/head')) 25 | ) 26 | -------------------------------------------------------------------------------- /app/templates/gulp/production/styles-production.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | const styles = require('@pixel2html/pipes').styles 4 | 5 | gulp.task('main:styles:prod', () => 6 | gulp.src(config.project.cssFiles) 7 | .pipe(styles({ 8 | modules: true, 9 | name: 'main.css', 10 | production: config.production 11 | })()) 12 | .pipe(gulp.dest(config.directories.dist.styles)) 13 | ) 14 | 15 | gulp.task('vendor:styles:prod', () => 16 | gulp.src(config.project.cssVendorFile) 17 | .pipe(styles({ 18 | modules: false, 19 | name: 'vendor.css', 20 | production: config.production 21 | })()) 22 | .pipe(gulp.dest(config.directories.dist.styles)) 23 | ) 24 | 25 | gulp.task('styles:prod', gulp.series('main:styles:prod', 'vendor:styles:prod', 'writeModules')) 26 | -------------------------------------------------------------------------------- /test/jquery.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | 5 | describe('jQuery features', function () { 6 | beforeEach(function () { 7 | return helpers.run(path.join(__dirname, '../app')) 8 | .withOptions({ 9 | 'skip-install': true 10 | }) 11 | .withPrompts({ 12 | projectName: 'Pixel2HTML', 13 | qtyScreens: 3, 14 | markupLanguage: 'html', 15 | frontEndFramework: 'bootstrap-4', 16 | jQuery: true 17 | }) 18 | .toPromise() 19 | }) 20 | 21 | it('should list dependencies in package.json', function () { 22 | assert.fileContent('package.json', /"jquery"/) 23 | }) 24 | 25 | it('should exists a gulp routine', function () { 26 | assert.file([ 27 | 'gulp/common/scripts.js' 28 | ]) 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /app/templates/gulp/common/styles.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | const styles = require('@pixel2html/pipes').styles 4 | 5 | gulp.task('main:styles', () => 6 | gulp.src(config.project.cssFiles) 7 | .pipe(styles({ 8 | modules: true, 9 | name: 'main.css', 10 | production: config.production 11 | })()) 12 | .on('error', config.onError) 13 | .pipe(gulp.dest(config.directories.dist.styles)) 14 | ) 15 | 16 | gulp.task('vendor:styles', () => 17 | gulp.src(config.project.cssVendorFile) 18 | .pipe(styles({ 19 | modules: false, 20 | name: 'vendor.css', 21 | production: config.production 22 | })()) 23 | .on('error', config.onError) 24 | .pipe(gulp.dest(config.directories.dist.styles)) 25 | ) 26 | 27 | gulp.task('styles', gulp.series('main:styles', 'vendor:styles', 'writeModules')) 28 | -------------------------------------------------------------------------------- /app/templates/gulp/development/serve.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | const browserSync = require('browser-sync') 4 | const openBrowser = require('react-dev-utils/openBrowser') 5 | const WebpackDevServerUtils = require('react-dev-utils/WebpackDevServerUtils') 6 | const {prepareUrls, choosePort} = WebpackDevServerUtils 7 | 8 | gulp.task('browser-sync', done => { 9 | const DEFAULT_PORT = 3000 10 | const HOST = '0.0.0.0' 11 | const protocol = 'http' 12 | choosePort(HOST, DEFAULT_PORT) 13 | .then(port => { 14 | if (port === null) return 15 | const urls = prepareUrls(protocol, HOST, port) 16 | browserSync.init({ 17 | port, 18 | server: { 19 | baseDir: config.directories.dist.base, 20 | serveStaticOptions: { 21 | extensions: ['html'] 22 | } 23 | }, 24 | open: false, 25 | logConnections: true, 26 | tunnel: config.tunnel, 27 | logPrefix: 'Pixel2Html', 28 | files: ['**/*.css'] 29 | }) 30 | openBrowser(urls.localUrlForBrowser) 31 | done() 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2018, Pixel2HTML. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/templates/base/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017, Pixel2HTML. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/templates/gulp/development/watch.js.ejs: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const browserSync = require('browser-sync') 3 | const config = require('../config') 4 | 5 | const reload = done => { 6 | browserSync.reload() 7 | done() 8 | } 9 | 10 | gulp.task('watch', done => { 11 | // static files 12 | gulp.watch(config.directories.src.markup+'/**/*.<%=markupLanguage%>', gulp.series( 'markup', reload )) 13 | <% if (markupLanguage === 'pug') { -%> 14 | gulp.watch(config.directories.src.icons+'/**/*.svg', gulp.series( 'markup', reload )) 15 | <% } else { -%> 16 | gulp.watch(config.directories.src.icons+'/**/*.svg', gulp.series( 'icons', reload )) 17 | <% } -%> 18 | gulp.watch(config.directories.src.images+'/**/*', gulp.series( 'images', reload )) 19 | gulp.watch(config.directories.src.base + '/assets/head/**/*', gulp.series('head', reload)) 20 | // Fonts 21 | gulp.watch(config.project.fontFiles, gulp.series('fonts', reload)) 22 | //styles 23 | gulp.watch(config.directories.src.styles + '/**/*.scss', gulp.series('styles')) 24 | // Scripts 25 | gulp.watch(config.directories.src.scripts + '/**/*.js', gulp.series('scripts', reload)) 26 | done() 27 | }) 28 | -------------------------------------------------------------------------------- /test/scripts.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | 5 | describe('Script features', function () { 6 | beforeEach(function () { 7 | return helpers.run(path.join(__dirname, '../app')) 8 | .withOptions({ 9 | 'skip-install': true 10 | }) 11 | .withPrompts({ 12 | projectName: 'Pixel2HTML', 13 | qtyScreens: 3, 14 | markupLanguage: 'html', 15 | frontEndFramework: 'bootstrap-4', 16 | jQuery: true 17 | }) 18 | .toPromise() 19 | }) 20 | 21 | it('creates expected base files', function () { 22 | assert.file([ 23 | 'src/assets/js/index.js', 24 | 'src/assets/js/app.js', 25 | 'webpack.config.js', 26 | 'webpack/commonPlugins.js', 27 | 'webpack/debugPlugins.js', 28 | 'webpack/developmentPlugins.js', 29 | 'webpack/paths.js', 30 | 'webpack/productionPlugins.js' 31 | ]) 32 | }) 33 | 34 | it('should exists a gulp routine', function () { 35 | assert.file([ 36 | 'gulp/common/scripts.js' 37 | ]) 38 | }) 39 | 40 | it('should have the project name on package.json', function () { 41 | assert.fileContent('src/assets/js/app.js', /Pixel2HTML/) 42 | }) 43 | }) 44 | -------------------------------------------------------------------------------- /app/templates/gulp/gulpfile.js.ejs: -------------------------------------------------------------------------------- 1 | const config = require('./gulp/config') 2 | const gulp = require('gulp') 3 | const prod = config.production 4 | 5 | const common = [ 6 | 'cssModulesWrite', 7 | 'fonts', 'markup', 8 | 'scripts', 'static', 9 | 'styles' 10 | ] 11 | const development = [ 12 | 'serve', 'watch' 13 | ] 14 | const production = [ 15 | 'minifyStyles', 'purify', 16 | 'styles-production', 'zip' 17 | ] 18 | 19 | common.forEach(file => require(`./gulp/common/${file}`)) 20 | prod 21 | ? production.forEach(file => require(`./gulp/production/${file}`)) 22 | : development.forEach(file => require(`./gulp/development/${file}`)) 23 | 24 | const prodTasks = [ 25 | 'minifyStyles', 26 | 'purify' 27 | ] 28 | 29 | let tasks = [ 30 | 'clean', 31 | config.production ? 'styles:prod' : 'styles', 32 | 'images', 'head', 33 | 'scripts', 'fonts', 34 | 'markup',<% if (markupLanguage === 'html') { %> 'icons',<% } %> 35 | prod && [...prodTasks] 36 | ] 37 | 38 | const filteredTasks = tasks.filter(task => !!task) 39 | gulp.task('build', gulp.series(...filteredTasks)) 40 | 41 | if (prod) { 42 | gulp.task('release', gulp.series('build', 'zip')) 43 | } else { 44 | gulp.task('serve', gulp.parallel('browser-sync', 'watch')) 45 | gulp.task('default', gulp.series('build', 'serve')) 46 | } 47 | -------------------------------------------------------------------------------- /app/templates/markup/_screen.html.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |Time to code 🐟
26 | 27 | 🐼🐼🐼🐼 Everything here will be replaced 🐼🐼🐼🐼 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /test/foundation.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | 5 | describe('Foundation features', function () { 6 | beforeEach(function () { 7 | return helpers.run(path.join(__dirname, '../app')) 8 | .withOptions({ 9 | 'skip-install': true 10 | }) 11 | .withPrompts({ 12 | projectName: 'Pixel2HTML', 13 | qtyScreens: 3, 14 | markupLanguage: 'html', 15 | frontEndFramework: 'foundation' 16 | }) 17 | .toPromise() 18 | }) 19 | 20 | it('Should exists dependencies in package.json', function () { 21 | assert.fileContent('package.json', /"foundation-sites"/) 22 | }) 23 | 24 | it('should exists a gulp routine', function () { 25 | assert.file([ 26 | 'gulp/common/styles.js', 27 | 'gulp/common/scripts.js' 28 | ]) 29 | }) 30 | it('should exists vendor files', function () { 31 | assert.file([ 32 | 'src/assets/styles/vendor/vendor.scss', 33 | 'src/assets/js/index.js' 34 | ]) 35 | }) 36 | 37 | it('should include foundation include', function () { 38 | assert.fileContent('src/assets/styles/vendor/vendor.scss', /import "foundation-sites\/scss\/foundation";/) 39 | assert.fileContent('src/assets/js/framework.js', /import 'foundation-sites'/) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /app/filesToAssert.js: -------------------------------------------------------------------------------- 1 | const baseFiles = [ 2 | 'LICENSE', 3 | 'webpack.config.js' 4 | ] 5 | 6 | const baseTemplates = [ 7 | 'package.json', 8 | 'README.md', 9 | ] 10 | 11 | const dotfiles = [ 12 | 'editorconfig', 13 | 'gitignore', 14 | 'gitattributes', 15 | 'project.conf' 16 | ] 17 | 18 | const webpack = [ 19 | 'webpack/commonPlugins.js', 20 | 'webpack/debugPlugins.js', 21 | 'webpack/developmentPlugins.js', 22 | 'webpack/paths.js', 23 | 'webpack/productionPlugins.js', 24 | ] 25 | 26 | const gulpFiles = [ 27 | 'gulp/common/cssModulesWrite.js', 28 | 'gulp/common/fonts.js', 29 | 'gulp/common/scripts.js', 30 | 'gulp/common/styles.js', 31 | 'gulp/development/serve.js', 32 | 'gulp/production/minifyStyles.js', 33 | 'gulp/production/purify.js', 34 | 'gulp/production/styles-production.js', 35 | 'gulp/production/zip.js', 36 | ] 37 | 38 | const gulpTemplates = [ 39 | 'gulpfile.js', 40 | 'gulp/config.js', 41 | 'gulp/common/markup.js', 42 | 'gulp/common/static.js', 43 | 'gulp/development/watch.js', 44 | ] 45 | 46 | const scss = [ 47 | 'styles/main/components/_buttons.scss', 48 | 'styles/main/components/_forms.scss', 49 | 'styles/main/screens/_base.scss', 50 | 'styles/main/_mixins.scss', 51 | 'styles/main/_variables.scss', 52 | 'styles/main/main.scss', 53 | 'styles/vendor/_reset.scss', 54 | 'styles/vendor/vendor.scss', 55 | ] 56 | 57 | module.exports = { 58 | baseFiles, 59 | baseTemplates, 60 | dotfiles, 61 | webpack, 62 | gulpFiles, 63 | gulpTemplates, 64 | scss, 65 | } 66 | -------------------------------------------------------------------------------- /test/general.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | 5 | describe('General Assertions', function () { 6 | beforeEach(function () { 7 | return helpers.run(path.join(__dirname, '../app')) 8 | .withOptions({ 9 | 'skip-install': true 10 | }) 11 | .withPrompts({ 12 | projectName: 'Pixel2HTML', 13 | qtyScreens: 6, 14 | markupLanguage: 'html' 15 | }) 16 | .toPromise() 17 | }) 18 | 19 | it('creates expected base files', function () { 20 | assert.file([ 21 | '.gitignore', 22 | '.gitattributes', 23 | 'package.json', 24 | 'gulpfile.js', 25 | 'package.json', 26 | 'webpack.config.js', 27 | '.tern-project', 28 | '.editorconfig', 29 | 'LICENSE', 30 | 'src/index.html', 31 | 'src/screen-2.html', 32 | 'src/screen-3.html', 33 | 'src/screen-4.html', 34 | 'src/screen-5.html', 35 | 'src/screen-6.html', 36 | 'gulp/config.js', 37 | 'gulp/common/styles.js', 38 | 'gulp/development/watch.js', 39 | 'gulp/development/serve.js', 40 | 'gulp/common/scripts.js', 41 | 'gulp/common/fonts.js', 42 | 'gulp/common/static.js', 43 | 'gulp/common/markup.js', 44 | 'gulp/production/minifyStyles.js', 45 | 'gulp/production/styles-production.js', 46 | 'gulp/production/purify.js', 47 | 'src/assets/head/favico.ico', 48 | 'src/assets/head/favicon.png', 49 | 'src/assets/head/manifest.json' 50 | ]) 51 | }) 52 | 53 | it('should have the project name on package.json', function () { 54 | assert.fileContent('package.json', /"name": "Pixel2HTML"/) 55 | }) 56 | }) 57 | -------------------------------------------------------------------------------- /docs/running_the_generator.md: -------------------------------------------------------------------------------- 1 | # Running the Pixel2HTML Generator 2 | 3 | ### Option 1: Answering the questions 4 | 5 | To generate the **Pixel2HTML Boilerplate** go to your project folder and run this command in your shell 6 | 7 | ``` 8 | $ cd ~/your/project/folder 9 | $ yo pixel2html 10 | ``` 11 | The **Pixel2HTML Boilerplate** will ask you questions about this points. Answering with the desired options will generate the code. 12 | 13 | * Project Name? 14 | * Quantity of screens? 15 | * Markup Language? _Options: HTML / Pug_ 16 | * Markup Integration? _Options: None / Jekyll_ 17 | * Frontend Framework _Options: None / Bootstrap 3.*/ Bootstrap 4 Beta / Foundation_ 18 | * jQuery? _Options: true / false_ 19 | 20 | 21 | ### Option 2: Using available parameters 22 | 23 | You also can answer this questions passing parameters to the generator command. 24 | 25 | Here there are the available questions: 26 | 27 | * `--projectName` (*string*) 28 | * `--qtyScreens` (*int*) 29 | * `--markupLanguage` (*string*) [html, pug] 30 | * `--markupIntegration` (*string*) [jekyll, none] 31 | * `--frontEndFramework` (*string*) [bootstrap, bootstrap-4, foundation, none] 32 | * `--jQuery` (*bool*) 33 | 34 | Example: 35 | 36 | ``` 37 | $ yo pixel2html --projectName=Floyd --markupLanguage='html' 38 | ``` 39 | 40 | ### Option 3: Using the config file 41 | 42 | You can create a `.project.conf` file in the root directory of your project. 43 | Here an example of it's structure: 44 | 45 | ``` 46 | { 47 | "projectName": 'XXX', 48 | "qtyScreens": 4, 49 | "markupLanguage": 'html', 50 | "markupIntegration": 'jekyll', 51 | "frontEndFramework": "bootstrap", 52 | "jQuery": true 53 | } 54 | ``` 55 | 56 | Once you answered all the question, you can hit at: 57 | ``` 58 | $ yo pixel2html 59 | ``` 60 | -------------------------------------------------------------------------------- /app/templates/markup/pug/layouts/layout-primary.pug.ejs: -------------------------------------------------------------------------------- 1 | doctype html 2 | html(lang='en') 3 | head 4 | block title 5 | title <%= projectName %> 6 | meta(charset='utf-8') 7 | meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1') 8 | meta(name="viewport" content="width=device-width, initial-scale=1") 9 | meta(name='description' content='<%= projectName %> - Scaffolded with Pixel2HTML Frontend Generator') 10 | meta(name='theme-color', content='#3e456c') 11 | link(rel='manifest' href='assets/head/manifest.json') 12 | link(rel="shortcut icon" href="assets/head/favico.ico") 13 | link(rel="icon" type="image/png" href="assets/head/favicon.png") 14 | if production 15 | link(rel='stylesheet', href='assets/css/vendor.min.css') 16 | link(rel='stylesheet', href='assets/css/main.min.css') 17 | else 18 | link(rel='stylesheet', href='assets/css/vendor.css') 19 | link(rel='stylesheet', href='assets/css/main.css') 20 | block head 21 | //- If extra head content is necessary per page, it can be added per screen 22 | 23 | body 24 | include includes/mixins 25 | include general/menu 26 | block content 27 | //- This gets replaced by content per page 28 | 29 | include general/footer 30 | block footer 31 | //- If extra footer content is necessary per page, it can be added per screen 32 | 33 | if production<% if(jQuery || frontEndFramework){ %> 34 | script(src='//code.jquery.com/jquery-3.2.1.min.js')<% } %> 35 | script(src='assets/js/vendor.min.js') 36 | script(src='assets/js/main.min.js') 37 | else 38 | script(src='assets/js/vendor.js') 39 | script(src='assets/js/main.js') 40 | block scripts 41 | //- Also if more scripts are needed you can hook in here <3 42 | -------------------------------------------------------------------------------- /app/templates/gulp/config.js.ejs: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // We use this to read flags in the command line 3 | const argv = require('yargs').argv 4 | // Add your conditions here 💅 5 | const production = !!argv.prod || !!argv.production 6 | const debug = !!argv.debug 7 | const tunnel = !!argv.tunnel 8 | 9 | module.exports = { 10 | directories: { 11 | src: { 12 | base: '<%= paths.src.base %>',<% if(markupLanguage == 'html'){ %> 13 | markup: '<%= paths.src.markup %>',<% } %><% if(markupLanguage == 'pug'){ %> 14 | markup: '<%= paths.src.markup %>/pug',<% } %> 15 | fonts: '<%= paths.src.fonts %>', 16 | icons: '<%= paths.src.icons %>', 17 | images: '<%= paths.src.images %>', 18 | scripts: '<%= paths.src.scripts %>', 19 | styles: '<%= paths.src.styles %>', 20 | cssModules: 'src/assets/cssModules/css.json' 21 | }, 22 | dist: { 23 | base: '<%= paths.dist.base %>', 24 | markup: '<%= paths.dist.markup %>', 25 | fonts: 'dist/assets/fonts', 26 | icons: 'dist/assets/icons', 27 | images: 'dist/assets/images', 28 | scripts: 'dist/assets/js', 29 | styles: 'dist/assets/css', 30 | } 31 | }, 32 | project: { 33 | cssFiles: 'src/assets/styles/main/**/!(_)*.scss', 34 | cssVendorFile: 'src/assets/styles/vendor/vendor.scss', 35 | jsMainFile: 'src/assets/js/index.js', 36 | fontFiles: [ 37 | '<%= paths.src.fonts %>/**/*'<% if(frontEndFramework == 'bootstrap-3'){ %>, 38 | './node_modules/bootstrap-sass/assets/fonts/**/*'<% } %> 39 | ] 40 | }, 41 | onError: function(error) { 42 | console.log(error.toString()) 43 | production 44 | ? process.exit(1) 45 | : this.emit('end') 46 | }, 47 | production, 48 | debug, 49 | tunnel, 50 | // Stuff for PurifyCss 51 | purify: ['./dist/**/*.js', './dist/**/*.html'] 52 | } 53 | -------------------------------------------------------------------------------- /app/templates/base/package.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= projectName %>", 3 | "description": "<%= projectName %> front end source code", 4 | "license": "MIT", 5 | "repository": "http://www.pixel2html.com", 6 | "version": "1.0.0", 7 | "scripts": { 8 | "start": "npm install", 9 | "code": "gulp", 10 | "build": "gulp build --prod", 11 | "release": "gulp release --prod", 12 | "lint:js": "eslint 'src/**/*.js'", 13 | "lint:scss": "stylelint 'src/**/*.scss'", 14 | "lint": "npm run lint:js; npm run lint:scss", 15 | "debug": "gulp scripts --debug" 16 | }, 17 | "dependencies": { 18 | "@babel/core": "^7.0.0-beta.39", 19 | "@babel/runtime": "^7.0.0-beta.39", 20 | "@pixel2html/babel-preset": "^0.8.1", 21 | "@pixel2html/eslint-config": "^1.2.0", 22 | "@pixel2html/pipes": "^2.0.0", 23 | "babel-loader": "8.0.0-beta.0", 24 | "del": "^3.0.0", 25 | "eslint": "^4.17.0", 26 | "eslint-loader": "^1.9.0", 27 | "fs-path": "^0.0.23", 28 | "gulp": "^4.0.0", 29 | <% if(frontEndFramework === 'bootstrap-4'){ -%> 30 | "bootstrap": "^4.0.0", 31 | "popper.js": "^1.12.9", 32 | <% } -%> 33 | <% if(frontEndFramework === 'bootstrap-3'){ -%> 34 | "bootstrap-sass": "^3.3.7", 35 | <% } -%> 36 | <% if(frontEndFramework === 'foundation'){ -%> 37 | "foundation-sites": "^6.4.3", 38 | <% } -%> 39 | <% if(jQuery || frontEndFramework){ -%> 40 | "jquery": "^3.3.1", 41 | <% } -%> 42 | "gulp-zip": "^4.1.0", 43 | "uglifyjs-webpack-plugin": "^1.1.8", 44 | "webpack": "^3.10.0", 45 | "yargs": "^11.0.0" 46 | }, 47 | "devDependencies": { 48 | "@pixel2html/stylelint-config": "^1.3.0", 49 | "browser-sync": "^2.23.6", 50 | "react-dev-utils": "^5.0.0", 51 | "stylelint": "^8.4.0", 52 | "webpack-bundle-analyzer": "^2.10.0" 53 | }, 54 | "stylelint": { 55 | "extends": "@pixel2html/stylelint-config" 56 | }, 57 | "eslintConfig": { 58 | "extends": "@pixel2html/eslint-config" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/templates/gulp/common/markup.js.ejs: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../config') 3 | const production = config.production 4 | <% if (markupLanguage === 'pug') { -%> 5 | const fs = require('fs') 6 | const pug = require('@pixel2html/pipes').pug 7 | <% } -%> 8 | <% if (markupLanguage === 'html') { -%> 9 | const html = require('@pixel2html/pipes').html 10 | const BASE = config.directories.dist.base 11 | 12 | // Epic h4xxxxx 13 | const JS_DIR = config.directories.dist.scripts.split(`${BASE}/`)[1] 14 | const CSS_DIR = config.directories.dist.styles.split(`${BASE}/`)[1] 15 | 16 | const JS_EXT = production ? '.min.js' : '.js' 17 | const CSS_EXT = production ? '.min.css' : '.css' 18 | 19 | const js = [ 20 | `${JS_DIR}/vendor${JS_EXT}`, 21 | `${JS_DIR}/main${JS_EXT}` 22 | ] 23 | 24 | if (production) js.unshift('//code.jquery.com/jquery-3.2.1.min.js') 25 | 26 | const css = [ 27 | `${CSS_DIR}/vendor${CSS_EXT}`, 28 | `${CSS_DIR}/main${CSS_EXT}` 29 | ] 30 | <% } -%> 31 | 32 | gulp.task('markup', () => 33 | gulp.src(config.directories.src.markup + '/*.<%=markupLanguage%>') 34 | <% if (markupLanguage === 'pug') { -%> 35 | .pipe(pug({ 36 | pug: { 37 | basedir: config.directories.src.markup, 38 | locals: { 39 | icon: name => fs.readFileSync(`./src/assets/icons/${name}.svg`), 40 | production 41 | } 42 | }, 43 | cssModules: `./${config.directories.src.cssModules}`, 44 | imgAutoSize: { 45 | root: `./${config.directories.dist.base}`, 46 | processEmptySize: true 47 | } 48 | })()) 49 | .on('error', config.onError) 50 | <% } -%> 51 | <% if (markupLanguage === 'html') { -%> 52 | .pipe(html({ 53 | cssModules: `./${config.directories.src.cssModules}`, 54 | imgAutoSize: { 55 | root: `./${config.directories.dist.base}`, 56 | processEmptySize: true 57 | }, 58 | htmlReplace: {js, css} 59 | })()) 60 | .on('error', config.onError) 61 | <% } -%> 62 | .pipe(gulp.dest(config.directories.dist.markup)) 63 | ) 64 | -------------------------------------------------------------------------------- /test/scss.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | 5 | import { scss } from '../app/filesToAssert' 6 | 7 | describe('SCSS features', function () { 8 | beforeEach(function () { 9 | return helpers.run(path.join(__dirname, '../app')) 10 | .withOptions({ 11 | 'skip-install': true 12 | }) 13 | .withPrompts({ 14 | projectName: 'Pixel2HTML', 15 | qtyScreens: 3, 16 | markupLanguage: 'html' 17 | }) 18 | .toPromise() 19 | }) 20 | 21 | it('should exists base SCSS file', function () { 22 | const styles = scss.map(file => `src/assets/${file}`) 23 | assert.file(styles) 24 | }) 25 | 26 | it('should exists screens SCSS files', function () { 27 | assert.file([ 28 | 'src/assets/styles/main/screens/screen_1.scss', 29 | 'src/assets/styles/main/screens/screen_2.scss', 30 | 'src/assets/styles/main/screens/screen_3.scss' 31 | ]) 32 | }) 33 | 34 | it('should have project and client ids on comments', function () { 35 | assert.fileContent('src/assets/styles/main/screens/screen_1.scss', /Pixel2HTML/) 36 | assert.fileContent('src/assets/styles/main/screens/screen_2.scss', /Pixel2HTML/) 37 | assert.fileContent('src/assets/styles/main/screens/screen_3.scss', /Pixel2HTML/) 38 | }) 39 | 40 | it('should have screen number on comments', function () { 41 | assert.fileContent('src/assets/styles/main/screens/screen_1.scss', /Screen 1/) 42 | assert.fileContent('src/assets/styles/main/screens/screen_2.scss', /Screen 2/) 43 | assert.fileContent('src/assets/styles/main/screens/screen_3.scss', /Screen 3/) 44 | }) 45 | 46 | it('should exists a gulp routine', function () { 47 | assert.file([ 48 | 'gulp/common/styles.js', 49 | 'gulp/common/cssModulesWrite.js', 50 | 'gulp/production/minifyStyles.js', 51 | 'gulp/production/purify.js', 52 | 'gulp/production/styles-production.js' 53 | ]) 54 | }) 55 | 56 | it('should exists a pipe in the main:styles routing', function () { 57 | assert.fileContent('gulp/common/styles.js', /styles/) 58 | }) 59 | }) 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pixel2html/generator-frontend", 3 | "description": "Pixel2HTML Boilerplate Generator", 4 | "version": "2.4.3", 5 | "repository": "https://github.com/Pixel2HTML/pixel2html-generator", 6 | "license": "MIT", 7 | "author": { 8 | "name": "Juan Manuel Garcia Olivares", 9 | "email": "jm@pixel2html.com" 10 | }, 11 | "contributors": [ 12 | { 13 | "name": "Miguel Palau", 14 | "email": "miguel@pixel2html.com", 15 | "url": "https://www.mpz.im/" 16 | }, 17 | { 18 | "name": "Diego Peralta", 19 | "url": "https://diego.earth/" 20 | }, 21 | { 22 | "name": "Bruno Belcastro", 23 | "url": "https://github.com/argen" 24 | }, 25 | { 26 | "name": "Matt Ginn", 27 | "url": "http://matt.codes/" 28 | }, 29 | { 30 | "name": "Juan Di Nella", 31 | "url": "https://github.com/juandinella" 32 | }, 33 | { 34 | "name": "Tomas Peralta", 35 | "url": "https://github.com/peraltatomas" 36 | } 37 | ], 38 | "keywords": [ 39 | "yeoman-generator" 40 | ], 41 | "scripts": { 42 | "lint": "eslint 'src/**/*.js' 'test/**/*.js'", 43 | "pretest": "npm run lint", 44 | "test": "mocha --timeout 5000 --require babel-register", 45 | "postversion": "git push; git push --tags", 46 | "commit": "git-cz" 47 | }, 48 | "main": "app/index.js", 49 | "dependencies": { 50 | "@pixel2html/eslint-config": "^1.2.0", 51 | "chalk": "^2.3.1", 52 | "eslint": "^4.18.0", 53 | "eslint-config-standard": "^11.0.0", 54 | "eslint-plugin-import": "^2.8.0", 55 | "eslint-plugin-node": "^6.0.0", 56 | "eslint-plugin-promise": "^3.6.0", 57 | "eslint-plugin-standard": "^3.0.1", 58 | "fs-extra": "^5.0.0", 59 | "gulp-eslint": "^4.0.2", 60 | "gulp-filter": "^5.1.0", 61 | "gulp-jsbeautifier": "^2.1.2", 62 | "mkdirp": "^0.5.1", 63 | "moment": "^2.20.1", 64 | "path": "^0.12.7", 65 | "update-notifier": "^2.3.0", 66 | "wiredep": "^4.0.0", 67 | "yeoman-generator": "^2.0.3" 68 | }, 69 | "devDependencies": { 70 | "babel-preset-env": "^1.6.1", 71 | "babel-register": "^6.26.0", 72 | "commitizen": "^2.9.6", 73 | "emoji-cz": "^0.3.0", 74 | "mocha": "^5.0.1", 75 | "yeoman-assert": "^3.1.0", 76 | "yeoman-test": "^1.7.0" 77 | }, 78 | "eslintConfig": { 79 | "extends": "@pixel2html/eslint-config", 80 | "env": { 81 | "browser": true, 82 | "node": true, 83 | "mocha": true 84 | } 85 | }, 86 | "config": { 87 | "commitizen": { 88 | "path": "./node_modules/emoji-cz" 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/bootstrap.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | 5 | describe('Bootstrap 4 features', function () { 6 | beforeEach(function () { 7 | return helpers.run(path.join(__dirname, '../app')) 8 | .withOptions({ 9 | 'skip-install': true 10 | }) 11 | .withPrompts({ 12 | projectName: 'Pixel2HTML', 13 | qtyScreens: 3, 14 | markupLanguage: 'html', 15 | frontEndFramework: 'bootstrap-4' 16 | }) 17 | .toPromise() 18 | }) 19 | 20 | it('Should list dependencies in package.json', function () { 21 | assert.fileContent('package.json', /"bootstrap"/) 22 | }) 23 | 24 | it('should exists a gulp routine', function () { 25 | assert.file([ 26 | 'gulp/common/styles.js', 27 | 'gulp/common/scripts.js' 28 | ]) 29 | }) 30 | 31 | it('should exists vendor files', function () { 32 | assert.file([ 33 | 'src/assets/styles/vendor/vendor.scss', 34 | 'src/assets/js/index.js' 35 | ]) 36 | }) 37 | 38 | it('should include bootstrap include', function () { 39 | assert.fileContent('src/assets/styles/vendor/vendor.scss', /import "bootstrap\/scss\/bootstrap.scss";/) 40 | assert.fileContent('src/assets/js/framework.js', /import 'bootstrap'/) 41 | }) 42 | }) 43 | 44 | describe('Bootstrap 3 features', function () { 45 | beforeEach(function () { 46 | return helpers.run(path.join(__dirname, '../app')) 47 | .withOptions({ 48 | 'skip-install': true 49 | }) 50 | .withPrompts({ 51 | projectName: 'Pixel2HTML', 52 | qtyScreens: 3, 53 | markupLanguage: 'html', 54 | frontEndFramework: 'bootstrap-3' 55 | }) 56 | .toPromise() 57 | }) 58 | 59 | it('Should list dependencies in package.json', function () { 60 | assert.fileContent('package.json', /"bootstrap-sass"/) 61 | }) 62 | 63 | it('should exists a gulp routine', function () { 64 | assert.file([ 65 | 'gulp/common/styles.js', 66 | 'gulp/common/scripts.js' 67 | ]) 68 | }) 69 | 70 | it('should exists vendor files', function () { 71 | assert.file([ 72 | 'src/assets/styles/vendor/vendor.scss', 73 | 'src/assets/js/index.js' 74 | ]) 75 | }) 76 | 77 | it('should include bootstrap include', function () { 78 | assert.fileContent('src/assets/styles/vendor/vendor.scss', /import "bootstrap-sass";/) 79 | assert.fileContent('src/assets/js/framework.js', /require\('bootstrap-sass'\)/) 80 | }) 81 | 82 | it('should include correct paths on config file', function () { 83 | assert.fileContent('gulp/config.js', './node_modules/bootstrap-sass/assets/fonts/**/*') 84 | }) 85 | }) 86 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.3.2 2 | - Removed jekyll 3 | - 100/100 lighthouse and google pagespeed insights 4 | - Bootstrap 4 out of beta 5 | - Fewer dependencies 6 | - Decouple gulp tasks from this package 7 | 8 | # 2.2.0 9 | - HMR 10 | - CSS HMR 11 | - PurifyCSS 12 | - CriticalCSS 13 | 14 | ### 2.1.0 15 | - Add Bootstrap 4 Beta as an Frontend Framework option 16 | - Decouple jQuery from bundle on production mode. 17 | - Keep alive the opened browser tab when you hit `npm run code`. Thanks Facebook! 18 | 19 | 20 | 21 | ### 2.0.0 22 | - Reduced number of total dependencies 23 | - Webpack integration to handle JS files 24 | - God mode svg inline icons with pug mixins 25 | - Unified fonts task 26 | - Deploy via FTP 27 | - Jekyll and HTML both are now Environment aware 💅 28 | - No more support to LESS & Stylus css preprocessors. (Help: https://github.com/Pixel2HTML/pixel2html-generator/wiki/Using-other-styles-preprocessor-language) 29 | - No more support to BassCss framework 30 | 31 | ### 1.3.5 32 | - Minor fixes. 33 | 34 | ### 1.3.4 35 | - Fixed some minor bugs on JS compilation. 36 | - Minor other fixes. 37 | 38 | ### 1.3.3 39 | - Fixed some minor bugs on Jekyll builds. 40 | - Smarter use of config variables to gulp routines. 41 | - Updated dependencies versions. 42 | - Some tests improvement. 43 | - `projectName` variable instead of `projectId` to generate more white label projects. 44 | 45 | ### 1.3.2 46 | - Fix some miss references to vendor fonts 47 | - Updated JS syntax to ES6 48 | - Minor fixes 49 | 50 | ### 1.3.1 51 | - Added missing references to vendor scripts on pug base files 52 | 53 | #### 1.3.0 54 | - Migrate to Gulp 4. 55 | - Import reset.css only when there no selected FrontEnd Framework. 56 | - Added `production` flag to gulp tasks to speed up the compilation process on `development` mode (no mins, no compressions). 57 | - Added CSScomb. 58 | - Added PurifyCSS. 59 | - Improvements in the PUG file structure, now it have some layouts, mixins and imports. 60 | - Moved `sourcemaps` to a external file. 61 | - Removed useless Gulp Plumber. 62 | - Added some SVG magic by default. 63 | 64 | #### 1.2.3 65 | - Added fonts support to default gulp routine. 66 | 67 | #### 1.2.2 68 | - Added `dist` directories configuration on `config.js` file. 69 | - Added Zurb Foundation initializer on `main.js` file. 70 | - Updated library versions. 71 | 72 | #### 1.2.1 73 | - Fixed version name. 74 | 75 | #### 1.2.0 76 | - Added Jekyll support. 77 | - Removed vendor gulp tasks in favor of `config.js`. 78 | - Added gulp group css media queries support. 79 | - Improved bower inclusion of libs on index.js. 80 | 81 | #### 1.1.2 82 | - Added PUG/Jade support. 83 | 84 | #### 1.1.0 85 | - Minor bugfixing. 86 | - Removed `gitlab-ci.yml` integration. 87 | - Add generator version to config file. 88 | 89 | #### 1.0.0 90 | - Initial release. -------------------------------------------------------------------------------- /app/templates/base/webpack.config.js: -------------------------------------------------------------------------------- 1 | const config = require('./gulp/config') 2 | const paths = require('./webpack/paths') 3 | 4 | const commonPlugins = require('./webpack/commonPlugins') 5 | const devPlugins = require('./webpack/developmentPlugins') 6 | const productionPlugins = require('./webpack/productionPlugins') 7 | 8 | const production = config.production 9 | const debug = config.debug 10 | 11 | let debugPlugins = [] 12 | 13 | if (debug) { 14 | debugPlugins = require('./webpack/debugPlugins') 15 | } 16 | 17 | let plugins = [ ...commonPlugins ] 18 | 19 | const shouldBeDebugMode = production || debug 20 | 21 | if (!shouldBeDebugMode) plugins = [...plugins, ...devPlugins] 22 | if (shouldBeDebugMode) plugins = [...plugins, ...productionPlugins] 23 | if (debug) plugins = [...plugins, ...debugPlugins] 24 | 25 | process.env.NODE_ENV = 'development' 26 | process.env.BABEL_ENV = 'development' 27 | 28 | if (shouldBeDebugMode) { 29 | process.env.NODE_ENV = 'production' 30 | process.env.BABEL_ENV = 'production' 31 | } 32 | 33 | module.exports = { 34 | entry: paths.entry, 35 | devtool: shouldBeDebugMode ? 'source-map' : 'inline-source-map', 36 | module: { 37 | rules: [ 38 | { 39 | test: /\.(js|jsx|mjs)$/, 40 | enforce: 'pre', 41 | use: [ 42 | { 43 | options: { 44 | eslintPath: require.resolve('eslint'), 45 | baseConfig: { 46 | extends: [require.resolve('@pixel2html/eslint-config')] 47 | }, 48 | ignore: false, 49 | useEslintrc: false 50 | }, 51 | loader: require.resolve('eslint-loader') 52 | } 53 | ], 54 | include: paths.src 55 | }, 56 | { 57 | test: /\.(js|jsx|mjs)$/, 58 | include: paths.src, 59 | use: { 60 | loader: 'babel-loader', 61 | options: { 62 | presets: [ 63 | require.resolve('@pixel2html/babel-preset') 64 | ], 65 | cacheDirectory: true 66 | } 67 | } 68 | } 69 | ]}, 70 | output: { 71 | filename: shouldBeDebugMode ? '[name].min.js' : '[name].js', 72 | chunkFilename: shouldBeDebugMode ? '[name].chunk.min.js' : '[name].chunk.js', 73 | path: paths.output, 74 | publicPath: '/' 75 | }, 76 | plugins, 77 | externals: shouldBeDebugMode ? { 78 | jquery: 'jQuery' 79 | } : {}, 80 | // Some libraries import Node modules but don't use them in the browser. 81 | // Tell Webpack to provide empty mocks for them so importing them works. 82 | node: { 83 | dgram: 'empty', 84 | fs: 'empty', 85 | net: 'empty', 86 | tls: 'empty', 87 | child_process: 'empty' 88 | }, 89 | resolve: { 90 | alias: { 91 | styles: paths.styles 92 | } 93 | }, 94 | bail: shouldBeDebugMode 95 | } 96 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@pixel2html.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /app/templates/styles/vendor/_reset.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ 2 | // stylelint-disable 3 | html { 4 | font-family: sans-serif; 5 | -ms-text-size-adjust: 100%; 6 | -webkit-text-size-adjust: 100%; 7 | } 8 | 9 | body { 10 | margin: 0; 11 | } 12 | 13 | article, 14 | aside, 15 | details, 16 | figcaption, 17 | figure, 18 | footer, 19 | header, 20 | hgroup, 21 | main, 22 | menu, 23 | nav, 24 | section, 25 | summary { 26 | display: block; 27 | } 28 | 29 | audio, 30 | canvas, 31 | progress, 32 | video { 33 | display: inline-block; 34 | vertical-align: baseline; 35 | } 36 | 37 | audio:not([controls]) { 38 | display: none; 39 | height: 0; 40 | } 41 | 42 | [hidden], 43 | template { 44 | display: none; 45 | } 46 | 47 | a { 48 | background-color: transparent; 49 | } 50 | 51 | a:active, 52 | a:hover { 53 | outline: 0; 54 | } 55 | 56 | abbr[title] { 57 | border-bottom: 1px dotted; 58 | } 59 | 60 | b, 61 | strong { 62 | font-weight: bold; 63 | } 64 | 65 | dfn { 66 | font-style: italic; 67 | } 68 | 69 | h1 { 70 | font-size: 2em; 71 | margin: 0.67em 0; 72 | } 73 | 74 | mark { 75 | background: #ff0; 76 | color: #000; 77 | } 78 | 79 | small { 80 | font-size: 80%; 81 | } 82 | 83 | sub, 84 | sup { 85 | font-size: 75%; 86 | line-height: 0; 87 | position: relative; 88 | vertical-align: baseline; 89 | } 90 | 91 | sup { 92 | top: -0.5em; 93 | } 94 | 95 | sub { 96 | bottom: -0.25em; 97 | } 98 | 99 | img { 100 | border: 0; 101 | } 102 | 103 | svg:not(:root) { 104 | overflow: hidden; 105 | } 106 | 107 | figure { 108 | margin: 1em 40px; 109 | } 110 | 111 | hr { 112 | box-sizing: content-box; 113 | height: 0; 114 | } 115 | 116 | pre { 117 | overflow: auto; 118 | } 119 | 120 | code, 121 | kbd, 122 | pre, 123 | samp { 124 | font-family: monospace, monospace; 125 | font-size: 1em; 126 | } 127 | 128 | button, 129 | input, 130 | optgroup, 131 | select, 132 | textarea { 133 | color: inherit; 134 | font: inherit; 135 | margin: 0; 136 | } 137 | 138 | button { 139 | overflow: visible; 140 | } 141 | 142 | button, 143 | select { 144 | text-transform: none; 145 | } 146 | 147 | button, 148 | html input[type="button"], 149 | input[type="reset"], 150 | input[type="submit"] { 151 | -webkit-appearance: button; 152 | cursor: pointer; 153 | } 154 | 155 | button[disabled], 156 | html input[disabled] { 157 | cursor: default; 158 | } 159 | 160 | button::-moz-focus-inner, 161 | input::-moz-focus-inner { 162 | border: 0; 163 | padding: 0; 164 | } 165 | 166 | input { 167 | line-height: normal; 168 | } 169 | 170 | input[type="checkbox"], 171 | input[type="radio"] { 172 | box-sizing: border-box; 173 | padding: 0; 174 | } 175 | 176 | input[type="number"]::-webkit-inner-spin-button, 177 | input[type="number"]::-webkit-outer-spin-button { 178 | height: auto; 179 | } 180 | 181 | input[type="search"] { 182 | -webkit-appearance: textfield; 183 | box-sizing: content-box; 184 | } 185 | 186 | input[type="search"]::-webkit-search-cancel-button, 187 | input[type="search"]::-webkit-search-decoration { 188 | -webkit-appearance: none; 189 | } 190 | 191 | fieldset { 192 | border: 1px solid #c0c0c0; 193 | margin: 0 2px; 194 | padding: 0.35em 0.625em 0.75em; 195 | } 196 | 197 | legend { 198 | border: 0; 199 | padding: 0; 200 | } 201 | 202 | textarea { 203 | overflow: auto; 204 | } 205 | 206 | optgroup { 207 | font-weight: bold; 208 | } 209 | 210 | table { 211 | border-collapse: collapse; 212 | border-spacing: 0; 213 | } 214 | 215 | td, 216 | th { 217 | padding: 0; 218 | } 219 | -------------------------------------------------------------------------------- /test/markup.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | 5 | describe('Markup Features', function () { 6 | describe('HTML Project', function () { 7 | beforeEach(function () { 8 | return helpers.run(path.join(__dirname, '../app')) 9 | .withOptions({ 10 | 'skip-install': true 11 | }) 12 | .withPrompts({ 13 | projectName: 'Pixel2HTML', 14 | qtyScreens: 6, 15 | markupLanguage: 'html' 16 | }) 17 | .toPromise() 18 | }) 19 | 20 | it('creates expected base files', function () { 21 | assert.file([ 22 | '.gitignore', 23 | '.gitattributes', 24 | 'package.json', 25 | 'gulpfile.js', 26 | 'package.json', 27 | '.editorconfig', 28 | 'src/index.html', 29 | 'src/screen-2.html', 30 | 'src/screen-3.html', 31 | 'src/screen-4.html', 32 | 'src/screen-5.html', 33 | 'src/screen-6.html' 34 | ]) 35 | }) 36 | 37 | it('should have the project name on package.json', function () { 38 | assert.fileContent('package.json', /"name": "Pixel2HTML"/) 39 | }) 40 | 41 | it('should exists a gulp routine', function () { 42 | assert.file(['gulp/common/markup.js']) 43 | }) 44 | 45 | it('should have the gulp routine in gulp default\'s task', function () { 46 | assert.fileContent('gulpfile.js', /'markup'/) 47 | assert.fileContent('gulpfile.js', /'icons'/) 48 | assert.noFileContent('gulpfile.js', /'jekyll'/) 49 | }) 50 | 51 | it('should have the projectName in the title tag', function () { 52 | assert.fileContent('src/index.html', /