├── .babelrc ├── .gitignore ├── .gitlab-ci.yml ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── __tests__ ├── baseFiles.js ├── dotfiles.js ├── gulpFiles.js ├── shopifyFiles.js └── staticFiles.js ├── example ├── .env.example ├── .gitignore ├── LICENSE ├── editorconfig ├── gulp │ ├── gulp.config.js │ └── tasks │ │ ├── clean.js │ │ ├── deploy.js │ │ ├── fonts.js │ │ ├── icons.js │ │ ├── images.js │ │ ├── scripts.js │ │ ├── serve.js │ │ ├── shopify.js │ │ ├── styles.js │ │ ├── watch.js │ │ └── zip.js ├── gulpfile.js ├── package.json ├── readme.md ├── src │ ├── fonts │ │ └── .gitkeep │ ├── icons │ │ └── gulp.svg │ ├── images │ │ └── shopify.svg │ ├── scripts │ │ └── index.js │ ├── styles │ │ ├── main.scss │ │ └── vendor.scss │ └── theme │ │ ├── config │ │ └── settings_schema.json │ │ ├── layout │ │ ├── checkout.liquid │ │ └── theme.liquid │ │ ├── locales │ │ ├── en.default.json │ │ └── es.json │ │ ├── sections │ │ └── featured-collection.liquid │ │ ├── snippets │ │ └── svg-icons.liquid │ │ └── templates │ │ ├── 404.liquid │ │ ├── article.liquid │ │ ├── blog.liquid │ │ ├── cart.liquid │ │ ├── collection.liquid │ │ ├── customers │ │ ├── account.liquid │ │ ├── activate_account.liquid │ │ ├── addresses.liquid │ │ ├── login.liquid │ │ ├── order.liquid │ │ ├── register.liquid │ │ └── reset_password.liquid │ │ ├── gift_card.liquid │ │ ├── index.liquid │ │ ├── list-collections.liquid │ │ ├── page.contact.liquid │ │ ├── page.liquid │ │ ├── password.liquid │ │ ├── product.liquid │ │ └── search.liquid └── webpack.config.js ├── package.json ├── pixel2html-logo.png ├── readme.md └── src └── app ├── index.js ├── lib ├── clean.js ├── copy.js ├── directories.js ├── filesToAssert.js └── mockPrompts.js └── templates ├── base ├── LICENSE ├── editorconfig ├── env ├── env.example ├── gitignore ├── gulpfile.js ├── package.json ├── readme.md └── webpack.config.js ├── fonts └── .gitkeep ├── gulp ├── gulp.config.js └── tasks │ ├── clean.js │ ├── deploy.js │ ├── fonts.js │ ├── icons.js │ ├── images.js │ ├── scripts.js │ ├── serve.js │ ├── shopify.js │ ├── styles.js │ ├── watch.js │ └── zip.js ├── icons └── gulp.svg ├── images └── shopify.svg ├── scripts └── index.js ├── styles ├── main.scss └── vendor.scss └── theme ├── config └── settings_schema.json ├── layout ├── checkout.liquid └── theme.liquid ├── locales ├── en.default.json └── es.json ├── sections └── featured-collection.liquid ├── snippets └── svg-icons.liquid └── templates ├── 404.liquid ├── article.liquid ├── blog.liquid ├── cart.liquid ├── collection.liquid ├── customers ├── account.liquid ├── activate_account.liquid ├── addresses.liquid ├── login.liquid ├── order.liquid ├── register.liquid └── reset_password.liquid ├── gift_card.liquid ├── index.liquid ├── list-collections.liquid ├── page.contact.liquid ├── page.liquid ├── password.liquid ├── product.liquid └── search.liquid /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "add-module-exports" 4 | ], 5 | "presets": [ 6 | ["env", 7 | { 8 | "targets": { 9 | "node": 6, 10 | "uglify": 2 11 | } 12 | }] 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | generators/* 3 | yarn.lock 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | test: 2 | image: node:8 3 | script: 4 | - yarn install 5 | - yarn test 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | __tests__ 3 | .babelrc 4 | .gitlab-ci.yml 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | node_js: 5 | - "8.9.0" 6 | 7 | cache: 8 | directories: 9 | - node_modules 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 3.0.0 2 | - Use webpack 3 | - Proper browsersync refresh situation 4 | - Better js debug code 5 | - Move towards ESLINT for JS linting 6 | - Separate watch tasks 7 | - After running the release task the browser opens for you to upload the final theme. 8 | 9 | #### 2.0.0 10 | - Moving away from Gulp Shopify Upload with Callbacks to Gulp Shopify Theme 11 | - Bug Fixes everywhere 12 | 13 | #### 1.0.0 14 | - Initial release 15 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /__tests__/baseFiles.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | import { baseFiles } from '../src/app/lib/filesToAssert' 5 | import { 6 | shopName, 7 | shopKey, 8 | shopPassword, 9 | shopSecret, 10 | shopThemeId 11 | } from '../src/app/lib/mockPrompts' 12 | 13 | describe('Base Files', function () { 14 | beforeEach(function () { 15 | return helpers.run(path.join(__dirname, '../generators/app')) 16 | .withOptions({ 17 | noAnims: true 18 | }) 19 | .withPrompts({ 20 | projectName: 'Awesome Test Project', 21 | setShopNow: true, 22 | shopName, 23 | shopKey, 24 | shopPassword, 25 | shopSecret, 26 | shopThemeId 27 | }) 28 | .toPromise() 29 | }) 30 | 31 | it('creates expected base files', function () { 32 | assert.file(baseFiles) 33 | }) 34 | 35 | it('Writes our options where we need them', function () { 36 | assert.fileContent('.env', shopName) 37 | assert.fileContent('.env', shopKey) 38 | assert.fileContent('.env', shopPassword) 39 | assert.fileContent('.env', shopSecret) 40 | assert.fileContent('.env', shopThemeId) 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /__tests__/dotfiles.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | import { dotfiles } from '../src/app/lib/filesToAssert' 5 | import { 6 | shopName, 7 | shopKey, 8 | shopPassword, 9 | shopSecret, 10 | shopThemeId 11 | } from '../src/app/lib/mockPrompts' 12 | 13 | describe('Base Files', function () { 14 | beforeEach(function () { 15 | return helpers.run(path.join(__dirname, '../generators/app')) 16 | .withOptions({ 17 | noAnims: true 18 | }) 19 | .withPrompts({ 20 | projectName: 'Awesome Test Project', 21 | setShopNow: true, 22 | shopName, 23 | shopKey, 24 | shopPassword, 25 | shopSecret, 26 | shopThemeId 27 | }) 28 | .toPromise() 29 | }) 30 | 31 | it('creates expected base files', function () { 32 | const transformedFiles = dotfiles.map(file => `.${file}`) 33 | assert.file(transformedFiles) 34 | }) 35 | 36 | it('Writes our options where we need them', function () { 37 | assert.fileContent('.env', shopName) 38 | assert.fileContent('.env', shopKey) 39 | assert.fileContent('.env', shopPassword) 40 | assert.fileContent('.env', shopSecret) 41 | assert.fileContent('.env', shopThemeId) 42 | }) 43 | }) 44 | -------------------------------------------------------------------------------- /__tests__/gulpFiles.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | import { gulpFiles } from '../src/app/lib/filesToAssert' 5 | import { 6 | shopName, 7 | shopKey, 8 | shopPassword, 9 | shopSecret, 10 | shopThemeId 11 | } from '../src/app/lib/mockPrompts' 12 | 13 | describe('Gulp Files', function () { 14 | beforeEach(function () { 15 | return helpers.run(path.join(__dirname, '../generators/app')) 16 | .withOptions({ 17 | noAnims: true 18 | }) 19 | .withPrompts({ 20 | projectName: 'Awesome Test Project', 21 | setShopNow: true, 22 | shopName, 23 | shopKey, 24 | shopPassword, 25 | shopSecret, 26 | shopThemeId 27 | }) 28 | .toPromise() 29 | }) 30 | 31 | it('creates expected gulp files', function () { 32 | const allFiles = gulpFiles.map(file => `gulp/${file}`) 33 | assert.file(allFiles) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /__tests__/shopifyFiles.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | import { shopifyCoreFiles } from '../src/app/lib/filesToAssert' 5 | import { 6 | shopName, 7 | shopKey, 8 | shopPassword, 9 | shopSecret, 10 | shopThemeId 11 | } from '../src/app/lib/mockPrompts' 12 | 13 | describe('General Assertions', function () { 14 | beforeEach(function () { 15 | return helpers.run(path.join(__dirname, '../generators/app')) 16 | .withOptions({ 17 | noAnims: true 18 | }) 19 | .withPrompts({ 20 | projectName: 'Awesome Test Project', 21 | setShopNow: true, 22 | shopName, 23 | shopKey, 24 | shopPassword, 25 | shopSecret, 26 | shopThemeId 27 | }) 28 | .toPromise() 29 | }) 30 | 31 | it('creates expected general files', function () { 32 | const shopifyFiles = shopifyCoreFiles.map(file => `src/theme/${file}`) 33 | assert.file(shopifyFiles) 34 | }) 35 | 36 | it('writes what we need in the shopify files', function () { 37 | assert.fileContent('src/theme/layout/theme.liquid', 'Awesome Test Project') 38 | assert.fileContent('src/theme/layout/checkout.liquid', 'Awesome Test Project') 39 | assert.fileContent('src/theme/config/settings_schema.json', 'Awesome Test Project') 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /__tests__/staticFiles.js: -------------------------------------------------------------------------------- 1 | import helpers from 'yeoman-test' 2 | import assert from 'yeoman-assert' 3 | import path from 'path' 4 | import { staticFiles } from '../src/app/lib/filesToAssert' 5 | import { 6 | shopName, 7 | shopKey, 8 | shopPassword, 9 | shopSecret, 10 | shopThemeId 11 | } from '../src/app/lib/mockPrompts' 12 | 13 | describe('Static Files', function () { 14 | beforeEach(function () { 15 | return helpers.run(path.join(__dirname, '../generators/app')) 16 | .withOptions({ 17 | noAnims: true 18 | }) 19 | .withPrompts({ 20 | projectName: 'Awesome Test Project', 21 | setShopNow: true, 22 | shopName, 23 | shopKey, 24 | shopPassword, 25 | shopSecret, 26 | shopThemeId 27 | }) 28 | .toPromise() 29 | }) 30 | 31 | it('creates expected static files', function () { 32 | const compiledFiles = staticFiles.map(file => `src/${file}`) 33 | assert.file(compiledFiles) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /example/.env.example: -------------------------------------------------------------------------------- 1 | SHOP_NAME='' 2 | SHOP_KEY='' 3 | SHOP_PASSWORD='' 4 | SHOP_SECRET='' 5 | SHOP_THEME_ID='' 6 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | dist/* 3 | .env 4 | dist 5 | releases 6 | .DS_Store 7 | settings_data.json 8 | -------------------------------------------------------------------------------- /example/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 | -------------------------------------------------------------------------------- /example/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 | -------------------------------------------------------------------------------- /example/gulp/gulp.config.js: -------------------------------------------------------------------------------- 1 | // We use this to read flags in the command line 2 | const production = process.env.NODE_ENV === 'production' 3 | const debug = process.env.DEBUG_MODE === 'true' 4 | 5 | module.exports = { 6 | theme: 'dist', 7 | shopify: { 8 | key: process.env.SHOP_KEY, 9 | pass: process.env.SHOP_PASSWORD, 10 | secret: process.env.SHOP_SECRET, 11 | themeId: process.env.SHOP_THEME_ID, 12 | shopName: process.env.SHOP_NAME, 13 | flatFolders: [ 14 | 'assets', 15 | 'config', 16 | 'layout', 17 | 'locales', 18 | 'templates' 19 | ], 20 | multiLevelFolders: [ 21 | 'sections', 22 | 'snippets' 23 | ] 24 | }, 25 | src: { 26 | styles: './src/styles', 27 | scripts: 'src/scripts', 28 | fonts: [ 29 | './src/fonts/**/*' 30 | ], 31 | icons: [ 32 | './src/icons/**/*' 33 | ], 34 | images: [ 35 | './src/images/**/*.{svg,png,jpg,jpeg,gif,ico}' 36 | ], 37 | shopify: [ 38 | './src/theme/**/*' 39 | ], 40 | theme: './src/theme' 41 | }, 42 | onError: function(error) { 43 | console.log(error.toString()) 44 | production 45 | ? 46 | process.exit(1) : 47 | this.emit('end') 48 | }, 49 | production, 50 | debug, 51 | // For autoprefixer 52 | browsers: [ 53 | 'last 2 Chrome versions', 54 | 'last 2 ChromeAndroid versions', 55 | 'last 2 Firefox versions', 56 | 'last 2 Safari versions', 57 | 'last 2 ios versions', 58 | 'last 1 ie versions', 59 | 'last 2 Edge versions', 60 | 'last 2 Opera versions' 61 | ], 62 | appendLiquidExt: path => { 63 | if (path.extname === '.map') return 64 | if (path.extname === '.css') { 65 | path.extname = '.scss' 66 | } 67 | path.basename += path.extname 68 | path.extname = '.liquid' 69 | }, 70 | makeLiquidSourceMappingURL: file => `{{ "${file.relative}.map" | asset_url }}`, 71 | flatten: path => { 72 | if (path.dirname !== '.') { 73 | path.basename = path.dirname.replace('/', '_') + '_' + path.basename 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /example/gulp/tasks/clean.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const del = require('del') 4 | 5 | gulp.task('clean', function() { 6 | return del([config.theme, 'releases']) 7 | }) -------------------------------------------------------------------------------- /example/gulp/tasks/deploy.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const watch = require('gulp-watch') 3 | const config = require('../gulp.config') 4 | const shopify = require('gulp-shopify-theme') 5 | const theme = shopify.create() 6 | 7 | const browserSync = require('browser-sync') 8 | 9 | const reload = () => { 10 | browserSync.reload() 11 | } 12 | 13 | const shopifyConfig = { 14 | api_key: config.shopify.key, 15 | password: config.shopify.pass, 16 | shared_secret: config.shopify.secret, 17 | shop_name: config.shopify.shopName, 18 | theme_id: config.shopify.themeId 19 | } 20 | 21 | const validKeys = Object.keys(shopifyConfig).filter(key => shopifyConfig[key]) 22 | const CAN_DEPLOY = validKeys.length > 0 23 | 24 | const themeFiles = config.theme + '/{assets,layout,config,snippets,templates,locales,sections}/**/*' 25 | 26 | gulp.task('theme:init', done => { 27 | if (CAN_DEPLOY) theme.init(shopifyConfig) 28 | done() 29 | }) 30 | 31 | gulp.task('theme:watch', done => 32 | CAN_DEPLOY ? 33 | watch(themeFiles, { 34 | verbose: true 35 | }) 36 | .pipe(theme.stream(undefined, () => { 37 | reload() 38 | done() 39 | })).on('error', config.onError) : 40 | done() 41 | ) 42 | 43 | gulp.task('theme:upload', () => CAN_DEPLOY ? 44 | gulp.src(themeFiles) 45 | .pipe(theme.stream()) 46 | .on('error', config.onError) : 47 | null 48 | ) 49 | 50 | gulp.task('deploy', gulp.series('theme:init', 'theme:upload')) 51 | 52 | // Danger Zone 💀 53 | gulp.task('theme:purge', function(done) { 54 | theme.purge() 55 | done() 56 | }) 57 | gulp.task('kill:theme', gulp.series('theme:init', 'theme:purge')) -------------------------------------------------------------------------------- /example/gulp/tasks/fonts.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | 4 | gulp.task('fonts', function() { 5 | return gulp.src(config.src.fonts) 6 | .pipe(gulp.dest(config.theme + '/assets')) 7 | }) -------------------------------------------------------------------------------- /example/gulp/tasks/icons.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const $ = require('gulp-load-plugins')() 4 | 5 | gulp.task('icons', function() { 6 | return gulp.src(config.src.icons) 7 | .pipe($.svgmin({ 8 | plugins: [{ 9 | removeStyleElement: true 10 | }, 11 | { 12 | removeAttrs: { 13 | attrs: ['fill', 'stroke', 'fill.*', 'stroke.*'] 14 | } 15 | } 16 | ], 17 | js2svg: { 18 | pretty: true 19 | } 20 | })) 21 | .pipe($.svgstore({ 22 | inlineSvg: true 23 | })) 24 | .pipe($.rename('svg-icons.liquid')) 25 | .pipe(gulp.dest(config.theme + '/snippets')) 26 | }) -------------------------------------------------------------------------------- /example/gulp/tasks/images.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const $ = require('gulp-load-plugins')() 4 | 5 | gulp.task('images', () => 6 | gulp.src(config.src.images) 7 | .pipe($.changedInPlace({ 8 | firstPass: true 9 | })) 10 | .pipe($.rename(config.flatten)) 11 | .pipe($.rename({ 12 | dirname: '', 13 | prefix: '' 14 | })) 15 | .pipe(gulp.dest(config.theme + '/assets')) 16 | ) -------------------------------------------------------------------------------- /example/gulp/tasks/scripts.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const webpack = require('webpack') 3 | const webpackConfig = require('../../webpack.config') 4 | const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages') 5 | 6 | gulp.task('scripts', () => 7 | new Promise(resolve => webpack(webpackConfig, (err, stats) => { 8 | if (err) console.log('Webpack', err) 9 | var rawMessages = stats.toJson({}, true) 10 | var messages = formatWebpackMessages(rawMessages) 11 | if (!messages.errors.length && !messages.warnings.length) { 12 | console.log(stats.toString({ 13 | chunks: false, 14 | colors: true 15 | })) 16 | } 17 | if (messages.errors.length) { 18 | console.log('Failed to compile.') 19 | messages.errors.forEach(e => console.log(e)) 20 | resolve() 21 | } 22 | if (messages.warnings.length) { 23 | console.log('Compiled with warnings.') 24 | messages.warnings.forEach(w => console.log(w)) 25 | } 26 | resolve() 27 | })) 28 | ) -------------------------------------------------------------------------------- /example/gulp/tasks/serve.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const browserSync = require('browser-sync') 4 | const WebpackDevServerUtils = require('react-dev-utils/WebpackDevServerUtils') 5 | const { 6 | choosePort 7 | } = WebpackDevServerUtils 8 | 9 | const DEFAULT_PORT = 3000 10 | const HOST = '0.0.0.0' 11 | 12 | gulp.task('browser-sync', done => { 13 | choosePort(HOST, DEFAULT_PORT) 14 | .then(port => { 15 | if (port === null) { 16 | return 17 | } 18 | browserSync.init({ 19 | port, 20 | open: true, 21 | logConnections: true, 22 | logPrefix: 'Pixel2Html', 23 | proxy: `https://${config.shopify.shopName}.myshopify.com`, 24 | startPath: `?preview_theme_id=${config.shopify.themeId}`, 25 | reloadDebounce: 2000 26 | }) 27 | done() 28 | }) 29 | }) -------------------------------------------------------------------------------- /example/gulp/tasks/shopify.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const $ = require('gulp-load-plugins')() 4 | 5 | const createShopifyTask = name => { 6 | gulp.task(`shopify:${name}`, () => 7 | gulp.src(config.src.theme + `/${name}/**/*`) 8 | .pipe($.changedInPlace({ 9 | firstPass: true 10 | })) 11 | .pipe(gulp.dest(config.theme + `/${name}`)) 12 | ) 13 | } 14 | 15 | const flattenShopifyTask = name => { 16 | gulp.task(`shopify:${name}`, () => 17 | gulp.src(config.src.theme + `/${name}/**/*`) 18 | .pipe($.changedInPlace({ 19 | firstPass: true 20 | })) 21 | .pipe($.flatten()) 22 | .pipe(gulp.dest(config.theme + `/${name}`)) 23 | ) 24 | } 25 | 26 | config.shopify.flatFolders.forEach(createShopifyTask) 27 | config.shopify.multiLevelFolders.forEach(flattenShopifyTask) 28 | 29 | const allFolders = [ 30 | ...config.shopify.flatFolders, 31 | ...config.shopify.multiLevelFolders 32 | ] 33 | 34 | const shopifyTaskNames = allFolders.map(folder => `shopify:${folder}`) 35 | 36 | gulp.task('shopify', gulp.parallel(...shopifyTaskNames)) -------------------------------------------------------------------------------- /example/gulp/tasks/styles.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const when = require('gulp-if') 4 | const $ = require('gulp-load-plugins')() 5 | const production = config.production 6 | const moduleImporter = require('sass-module-importer') 7 | 8 | const destination = config.theme + '/assets' 9 | 10 | gulp.task('main:styles', function() { 11 | return gulp.src(config.src.styles + '/main.scss') 12 | .pipe(when(!production, $.sourcemaps.init())) 13 | .pipe($.sass({ 14 | importer: moduleImporter() 15 | })) 16 | .on('error', $.sass.logError) 17 | .pipe($.autoprefixer({ 18 | browsers: config.browsers 19 | })) 20 | .pipe(when(production, $.groupCssMediaQueries())) 21 | .pipe(when(production, $.csscomb())) 22 | .pipe(when(!production, $.sourcemaps.write('.', { 23 | sourceMappingURL: config.makeLiquidSourceMappingURL 24 | }))) 25 | .pipe(when(production, $.cssnano())) 26 | .pipe($.rename(config.appendLiquidExt)) // main.css.liquid 27 | .pipe(gulp.dest(destination)) 28 | }) 29 | 30 | gulp.task('vendor:styles', function() { 31 | return gulp.src(config.src.styles + '/vendor.scss') 32 | .pipe(when(!production, $.sourcemaps.init())) 33 | .pipe($.sass({ 34 | importer: moduleImporter() 35 | })) 36 | .on('error', $.sass.logError) 37 | .pipe($.autoprefixer({ 38 | browsers: config.browsers 39 | })) 40 | .pipe(when(production, $.groupCssMediaQueries())) 41 | .pipe(when(production, $.csscomb())) 42 | .pipe(when(!production, $.sourcemaps.write('.', { 43 | sourceMappingURL: config.makeLiquidSourceMappingURL 44 | }))) 45 | .pipe(when(production, $.cssnano())) 46 | .pipe($.rename(config.appendLiquidExt)) // vendor.css.liquid 47 | .pipe(gulp.dest(destination)) 48 | }) 49 | 50 | gulp.task('styles', gulp.parallel('main:styles', 'vendor:styles')) -------------------------------------------------------------------------------- /example/gulp/tasks/watch.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | 4 | const createShopifyWatchTask = name => { 5 | gulp.watch(config.src.theme + `/${name}/**/*`, gulp.series(`shopify:${name}`)) 6 | } 7 | const SHOPIFY_FOLDERS = [ 8 | ...config.shopify.flatFolders, 9 | ...config.shopify.multiLevelFolders 10 | ] 11 | 12 | gulp.task('watch', done => { 13 | gulp.watch(config.src.fonts, gulp.series('fonts')) 14 | gulp.watch(config.src.icons, gulp.series('icons')) 15 | gulp.watch(config.src.images, gulp.series('images')) 16 | gulp.watch(config.src.scripts + '/**/*', gulp.series('scripts')) 17 | gulp.watch(config.src.styles + '/**/*', gulp.series('styles')) 18 | SHOPIFY_FOLDERS.forEach(createShopifyWatchTask) 19 | done() 20 | }) -------------------------------------------------------------------------------- /example/gulp/tasks/zip.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const zip = require('gulp-zip') 4 | const pkg = require('../../package.json') 5 | const version = pkg.version 6 | const zipName = `v.${version} - MASTER.zip` 7 | 8 | const openBrowser = require('react-dev-utils/openBrowser') 9 | 10 | const distFiles = [ 11 | `${config.theme}/**`, 12 | `!${config.theme}` 13 | ] 14 | 15 | gulp.task('zip', () => 16 | gulp.src(distFiles, { 17 | base: '.' 18 | }) 19 | .pipe(zip(zipName)).on('error', config.onError) 20 | .pipe(gulp.dest('releases')) 21 | ) 22 | 23 | gulp.task('openBrowser', done => { 24 | openBrowser(`https://${config.shopify.shopName}.myshopify.com/admin/themes`) 25 | done() 26 | }) -------------------------------------------------------------------------------- /example/gulpfile.js: -------------------------------------------------------------------------------- 1 | const dotenv = require('dotenv') 2 | dotenv.config() 3 | 4 | const gulp = require('gulp') 5 | const requireDir = require('require-dir') 6 | 7 | requireDir('gulp', { 8 | recurse: true 9 | }) 10 | 11 | gulp.task('build', gulp.series( 12 | 'clean', 13 | 'fonts', 14 | 'icons', 15 | 'images', 16 | 'scripts', 17 | 'styles', 18 | 'shopify' 19 | )) 20 | 21 | gulp.task('release', gulp.series('build', 'zip')) 22 | 23 | gulp.task('serve', gulp.parallel( 24 | 'browser-sync', 25 | 'theme:init', 26 | 'theme:watch', 27 | 'watch' 28 | )) 29 | 30 | gulp.task('full-deploy', gulp.series('build', 'deploy')) 31 | 32 | gulp.task('default', gulp.series('build', 'serve')) -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Pixel2Html-BikeShop", 3 | "description": "Easy Scaffolding powered by Pixel2Html Shopify Skeleton", 4 | "license": "MIT", 5 | "repository": "http://www.pixel2html.com", 6 | "version": "1.0.0", 7 | "scripts": { 8 | "start": "npm install", 9 | "code": "cross-env NODE_ENV=development gulp", 10 | "release": "cross-env NODE_ENV=production gulp release", 11 | "build": "cross-env NODE_ENV=production gulp build", 12 | "deploy": "cross-env NODE_ENV=production gulp full-deploy", 13 | "kill-theme": "cross-env NODE_ENV=development gulp kill:theme", 14 | "webpack": "cross-env NODE_ENV=development webpack", 15 | "webpack:prod": "cross-env NODE_ENV=production webpack", 16 | "debug": "cross-env NODE_ENV=development cross-env DEBUG_MODE=true webpack", 17 | "debug:prod": "cross-env NODE_ENV=production cross-env DEBUG_MODE=true webpack", 18 | "lint:js": "eslint 'src/scripts/**/*.js'", 19 | "lint:scss": "stylelint 'src/styles/**/*.scss'", 20 | "lint": "npm run lint:js; npm run lint:scss" 21 | }, 22 | "dependencies": { 23 | "@babel/core": "^7.0.0-beta.38", 24 | "@babel/runtime": "^7.0.0-beta.38", 25 | "@pixel2html/babel-preset": "^0.7.0", 26 | "babel-loader": "8.0.0-beta.0", 27 | "cross-env": "^5.1.3", 28 | "del": "^3.0.0", 29 | "dotenv": "^4.0.0", 30 | "eslint-loader": "^1.9.0", 31 | "gulp": "^4.0.0", 32 | "gulp-autoprefixer": "^4.0.0", 33 | "gulp-changed-in-place": "^2.3.0", 34 | "gulp-concat": "^2.6.1", 35 | "gulp-csscomb": "^3.0.8", 36 | "gulp-cssnano": "^2.1.2", 37 | "gulp-flatten": "^0.3.1", 38 | "gulp-group-css-media-queries": "^1.2.0", 39 | "gulp-if": "^2.0.2", 40 | "gulp-load-plugins": "^1.5.0", 41 | "gulp-pug": "^3.3.0", 42 | "gulp-rename": "^1.2.2", 43 | "gulp-sass": "^3.1.0", 44 | "gulp-shopify-theme": "mike3run/gulp-shopify-theme", 45 | "gulp-sourcemaps": "^2.6.1", 46 | "gulp-svgmin": "^1.2.4", 47 | "gulp-svgstore": "^6.1.0", 48 | "gulp-uglify": "^3.0.0", 49 | "gulp-watch": "^4.3.11", 50 | "gulp-zip": "^4.0.0", 51 | "jquery": "^3.2.1", 52 | "require-dir": "^0.3.2", 53 | "sass-module-importer": "^1.4.0", 54 | "svg4everybody": "^2.1.9", 55 | "uglifyjs-webpack-plugin": "^1.1.4", 56 | "webpack": "^3.10.0" 57 | }, 58 | "devDependencies": { 59 | "@pixel2html/eslint-config": "^1.0.0", 60 | "@pixel2html/stylelint-config": "^1.3.0", 61 | "browser-sync": "^2.18.13", 62 | "eslint": "^4.14.0", 63 | "react-dev-utils": "^4.2.1", 64 | "stylelint": "^8.4.0", 65 | "webpack-bundle-analyzer": "^2.9.1", 66 | "webpack-monitor": "^1.0.14" 67 | }, 68 | "stylelint": { 69 | "extends": "@pixel2html/stylelint-config" 70 | }, 71 | "eslintConfig": { 72 | "extends": "@pixel2html/eslint-config" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /example/readme.md: -------------------------------------------------------------------------------- 1 | # Pixel2Html-BikeShop 2 | 3 | ## Scaffolded by Shopify Skeleton Version 3.0.5 4 | 5 | Easy Shopify Development 💅 6 | 7 | ## Important 8 | 9 | Your code will *not* compile unless you provide your Shopify API variables for the deploy task. 10 | Add them in the `.env` they will not be commited or shared this is for security reasons. 11 | 12 | 13 | ## Quick Start 14 | 15 | Compile things and auto upload to shopify 16 | 17 | ```bash 18 | $ npm run code 19 | ``` 20 | 21 | Zip everything and code in production mode 22 | 23 | ```bash 24 | $ npm run build 25 | ``` 26 | 27 | Full Deployment (useful with CI or during first time upload) 28 | 29 | ```bash 30 | $ npm run deploy 31 | ``` 32 | 33 | Delete Theme Files. Use with care!! (Good during first time upload) 34 | 35 | ```bash 36 | $ npm run kill-theme 37 | ``` 38 | 39 | ## Features 40 | 41 | - Sourcemaps 42 | - JS with Browserify and ES6 (Just require your problems away) 43 | - Split vendor and app code (both JS and CSS) 44 | - SVG System 45 | - Shopify Plus in mind (Checkout layouts) 46 | - Sensible starting points (all in blank but already wired up) 47 | - Based of Gulp 4 48 | - Live reloading with Browser Sync 49 | - Zip everything in the end 50 | 51 | -------------------------------------------------------------------------------- /example/src/fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/fonts/.gitkeep -------------------------------------------------------------------------------- /example/src/icons/gulp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/src/images/shopify.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/src/scripts/index.js: -------------------------------------------------------------------------------- 1 | // EXAMPLE DELETE EVERYTHING BELOW 2 | // Learn more about ES6 Here: 3 | // http://wesbos.com/javascript-modules/ 4 | // https://babeljs.io/learn-es2015/ 5 | 6 | const colors = ['pink', 'red', 'blue'] 7 | const moColors = ['blue', 'orange'] 8 | 9 | // We have Es6 Goodies thanks to Babel 10 | const allTheColors = [...colors, ...moColors] 11 | allTheColors.map(c => console.log(c)) -------------------------------------------------------------------------------- /example/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | .is-hidden { 2 | position: absolute; 3 | height: 0; 4 | width: 0; 5 | visibility: hidden; 6 | } 7 | 8 | svg[class^="icon-"] { 9 | fill: currentColor; 10 | stroke: none; 11 | max-width: 100%; 12 | } 13 | -------------------------------------------------------------------------------- /example/src/styles/vendor.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/styles/vendor.scss -------------------------------------------------------------------------------- /example/src/theme/config/settings_schema.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "theme_info", 3 | "logo": "https:\/\/cdn.shopify.com\/s\/global\/branding\/shopify_logo_256x256.png", 4 | "settings": [{ 5 | "type": "header", 6 | "content": "Pixel2Html BikeShop" 7 | }, 8 | { 9 | "type": "paragraph", 10 | "content": "Scaffolded with Pixel2HTML's Shopify Skeleton" 11 | } 12 | ] 13 | }] -------------------------------------------------------------------------------- /example/src/theme/layout/checkout.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Pixel2Html BikeShop 9 | {% if page_description %} {% endif %} 10 | 11 | 12 | {{ checkout_stylesheets }} 13 | {{ 'fonts.css' | asset_url | stylesheet_tag }} 14 | {{ 'vendor.css' | asset_url | stylesheet_tag }} 15 | {{ 'main.css' | asset_url | stylesheet_tag }} 16 | {{ content_for_header }} 17 | 18 | 19 | 20 | 21 | 22 | {{ content_for_order_summary }} 23 | {{ content_for_layout }} 24 | 25 | {{ "vendor.js" | asset_url | script_tag }} 26 | {{ "app.js" | asset_url | script_tag }} 27 | 28 | 29 | -------------------------------------------------------------------------------- /example/src/theme/layout/theme.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Pixel2Html BikeShop 9 | {% if page_description %} {% endif %} 10 | 11 | 12 | 13 | {{ 'vendor.scss' | asset_url | stylesheet_tag }} 14 | {{ 'main.scss' | asset_url | stylesheet_tag }} 15 | {{ content_for_header }} 16 | 17 | 18 | 19 | 20 | 21 | {{ content_for_layout }} 22 | {{ "https://code.jquery.com/jquery-3.2.1.min.js" | script_tag }} 23 | {{ "vendor.js" | asset_url | script_tag }} 24 | {{ "main.js" | asset_url | script_tag }} 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/src/theme/locales/en.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "cart": { 3 | "remove": "Remove", 4 | "update": "Update" 5 | } 6 | } -------------------------------------------------------------------------------- /example/src/theme/locales/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "cart": { 3 | "remove": "Remover", 4 | "update": "Actualizar" 5 | } 6 | } -------------------------------------------------------------------------------- /example/src/theme/sections/featured-collection.liquid: -------------------------------------------------------------------------------- 1 | {% if section.settings.title != blank %} 2 |

{{ section.settings.title | escape }}

3 | {% endif %} 4 | 5 | {%- assign collection = collections[section.settings.collection] -%} 6 | 7 | {% for product in collection.products limit: 6 %} 8 | 9 | {{ product.featured_image.src | img_url: '480x480' | img_tag: product.title }} 10 |

{{ product.title }}

11 |
12 | 13 |

14 | {% if product.compare_at_price > product.price %} 15 | 16 | {% if product.price_varies %} 17 | {%- assign sale_price = product.price | money -%} 18 | {{ 'products.product.on_sale_from_html' | t: price: sale_price }} 19 | {% else %} 20 | {{ 'products.product.on_sale' | t }} 21 | {{ product.price | money }} 22 | {% endif %} 23 | 24 | {% else %} 25 | 26 | {% if product.price_varies %} 27 | {%- assign price = product.price | money -%} 28 | {{ 'products.product.from_text_html' | t: price: price }} 29 | {% else %} 30 | {{ product.price | money }} 31 | {% endif %} 32 | 33 | {% endif %} 34 |

35 | {% else %} 36 | 37 | {% for i in (1..6) %} 38 | 39 | {% capture current %}{% cycle 1, 2, 3, 4, 5, 6 %}{% endcapture %} 40 | {{ 'product-' | append: current | placeholder_svg_tag: 'placeholder-svg placeholder-svg--small' }} 41 | 42 |

43 | {{ 'homepage.onboarding.product_title' | t }} 44 |

45 |
46 | 47 |

{{ 1999 | money }}

48 | {% endfor %} 49 | {% endfor %} 50 | 51 | {% schema %} 52 | { 53 | "name": "Featured collection", 54 | "settings": [ 55 | { 56 | "type": "text", 57 | "id": "title", 58 | "label": "Heading", 59 | "default": "Featured collection" 60 | }, 61 | { 62 | "id": "collection", 63 | "type": "collection", 64 | "label": "Collection" 65 | } 66 | ], 67 | "presets": [ 68 | { 69 | "name": "Featured collection", 70 | "category": "Collection" 71 | } 72 | ] 73 | } 74 | {% endschema %} 75 | -------------------------------------------------------------------------------- /example/src/theme/snippets/svg-icons.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/snippets/svg-icons.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/404.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/404.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/article.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/article.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/blog.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/blog.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/cart.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/cart.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/collection.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/collection.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/customers/account.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/customers/account.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/customers/activate_account.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/customers/activate_account.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/customers/addresses.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/customers/addresses.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/customers/login.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/customers/login.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/customers/order.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/customers/order.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/customers/register.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/customers/register.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/customers/reset_password.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/customers/reset_password.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/gift_card.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/gift_card.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/index.liquid: -------------------------------------------------------------------------------- 1 |

Pixel2HTML Shopify Skeleton

2 |

Pixel2Html BikeShop

3 |

Change stuff and fly away

4 | -------------------------------------------------------------------------------- /example/src/theme/templates/list-collections.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/list-collections.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/page.contact.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/page.contact.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/page.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/page.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/password.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/password.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/product.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/product.liquid -------------------------------------------------------------------------------- /example/src/theme/templates/search.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/example/src/theme/templates/search.liquid -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin') 3 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 4 | const config = require('./gulp/gulp.config') 5 | const { 6 | cwd, 7 | env 8 | } = require('process') 9 | 10 | const production = config.production 11 | const debug = config.debug 12 | const WebpackMonitor = require('webpack-monitor') 13 | 14 | // When you really want to make the relationship work... 15 | const ENTRY_PATH = cwd() + '/' + config.src.scripts 16 | const OUTPUT_PATH = cwd() + '/' + config.theme + '/assets' 17 | 18 | let plugins = [ 19 | // Add the env to remove excess skin 20 | new webpack.DefinePlugin({ 21 | 'process.env': { 22 | NODE_ENV: JSON.stringify(env.NODE_ENV) 23 | } 24 | }), 25 | new webpack.SourceMapDevToolPlugin({ 26 | filename: '[name].js.map', 27 | append: '\n//# sourceMappingURL={{ "[url]" | asset_url }}', 28 | test: /\.(js|liquid)$/ 29 | }), 30 | // Add module names to factory functions so they appear in browser profiler. 31 | new webpack.NamedModulesPlugin(), 32 | // Allow everyone to use jQuery like it was global 33 | new webpack.ProvidePlugin({ 34 | $: 'jquery', 35 | jQuery: 'jquery', 36 | 'window.jQuery': 'jquery' 37 | }), 38 | // Separate node_modules packages 39 | new webpack.optimize.CommonsChunkPlugin({ 40 | name: 'vendor', 41 | minChunks: module => /node_modules/.test(module.resource) 42 | }), 43 | // Do NOT import the BLOAT from moment.js 44 | // thanks create-react-app 45 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) 46 | ] 47 | 48 | const productionPlugins = [ 49 | // Concatenate modules for smaller builds 50 | new webpack.optimize.ModuleConcatenationPlugin(), 51 | // Uglify the heck out of this 52 | new UglifyJSPlugin({ 53 | sourceMap: true, 54 | test: /\.(js|liquid)$/ 55 | }) 56 | ] 57 | 58 | const debugPlugins = [ 59 | new BundleAnalyzerPlugin(), 60 | new WebpackMonitor({ 61 | target: cwd() + '/gulp/stats.json', 62 | launch: true, 63 | port: 5000 64 | }) 65 | ] 66 | 67 | if (production) plugins = [...plugins, ...productionPlugins] 68 | if (debug) plugins = [...plugins, ...debugPlugins] 69 | 70 | const CONFIG = { 71 | entry: ENTRY_PATH, 72 | module: { 73 | rules: [{ 74 | test: /\.(js|jsx)$/, 75 | exclude: /node_modules/, 76 | enforce: 'pre', 77 | use: { 78 | loader: 'eslint-loader' 79 | } 80 | }, 81 | { 82 | test: /\.(js|jsx)$/, 83 | exclude: /node_modules/, 84 | use: { 85 | loader: 'babel-loader', 86 | options: { 87 | presets: [ 88 | require.resolve('@pixel2html/babel-preset') 89 | ], 90 | cacheDirectory: true 91 | } 92 | } 93 | } 94 | ] 95 | }, 96 | output: { 97 | filename: debug ? '[name].js' : '[name].js.liquid', 98 | path: OUTPUT_PATH 99 | }, 100 | plugins, 101 | externals: { 102 | jquery: 'jQuery' 103 | }, 104 | // Some libraries import Node modules but don't use them in the browser. 105 | // Tell Webpack to provide empty mocks for them so importing them works. 106 | node: { 107 | dgram: 'empty', 108 | fs: 'empty', 109 | net: 'empty', 110 | tls: 'empty', 111 | child_process: 'empty' 112 | } 113 | } 114 | 115 | module.exports = CONFIG -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pixel2html/generator-shopify", 3 | "version": "3.0.6", 4 | "description": "Scaffold and develop shopify themes quickly", 5 | "author": "Miguel Palau ", 6 | "scripts": { 7 | "copy": "node src/app/lib/copy", 8 | "clean": "node src/app/lib/clean", 9 | "compile": " babel -d generators/ --ignore templates/ generators/", 10 | "get-ready": "npm run clean; npm run copy; npm run compile", 11 | "prepare": "npm run get-ready", 12 | "lint": "eslint 'src/**/*.js'", 13 | "pretest": "npm run get-ready", 14 | "test": "npm run lint; jest", 15 | "postversion": "git push; git push --tags" 16 | }, 17 | "files": [ 18 | "generators/app" 19 | ], 20 | "main": "src/app/index.js", 21 | "keywords": [ 22 | "yeoman-generator", 23 | "babel", 24 | "shopify" 25 | ], 26 | "repository": "git@github.com:Pixel2HTML/shopify-skeleton.git", 27 | "license": "MIT", 28 | "dependencies": { 29 | "chalk": "^2.3.0", 30 | "cowsay-browser": "^1.1.8", 31 | "gulp-filter": "^5.1.0", 32 | "gulp-jsbeautifier": "^2.1.2", 33 | "sync-parrot-api": "^1.0.2", 34 | "update-notifier": "^2.3.0", 35 | "yeoman-generator": "^2.0.2" 36 | }, 37 | "devDependencies": { 38 | "@pixel2html/eslint-config": "^1.0.0", 39 | "babel-cli": "^6.26.0", 40 | "babel-jest": "^22.1.0", 41 | "babel-plugin-add-module-exports": "^0.2.1", 42 | "babel-preset-env": "^1.6.1", 43 | "eslint": "^4.14.0", 44 | "eslint-plugin-import": "^2.8.0", 45 | "eslint-plugin-node": "^5.2.1", 46 | "eslint-plugin-promise": "^3.6.0", 47 | "fs-extra": "^5.0.0", 48 | "jest": "^22.1.4", 49 | "npm-bump": "^0.0.23", 50 | "yeoman-assert": "^3.1.0", 51 | "yeoman-test": "^1.7.0" 52 | }, 53 | "engines": { 54 | "node": ">=8.0.0" 55 | }, 56 | "eslintConfig": { 57 | "extends": "@pixel2html/eslint-config", 58 | "env": { 59 | "browser": true, 60 | "node": true, 61 | "mocha": true 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /pixel2html-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/pixel2html-logo.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Pixel2HTML Shopify Skeleton Generator 2 | 3 | [![npm version](https://badge.fury.io/js/%40pixel2html%2Fgenerator-shopify.svg)](https://badge.fury.io/js/%40pixel2html%2Fgenerator-shopify) 4 | [![Build Status](https://travis-ci.org/Pixel2HTML/shopify-skeleton.svg?branch=master)](https://travis-ci.org/Pixel2HTML/shopify-skeleton) 5 | [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) 6 | [![dependencies Status](https://david-dm.org/Pixel2HTML/shopify-skeleton/status.svg)](https://david-dm.org/Pixel2HTML/shopify-skeleton) 7 | 8 | This is a tool for scaffolding Shopify themes quickly. Built as a starting point like Slate but with more flexibility in mind. 9 | 10 | Brought to you by ~> 11 | Pixel2HTML Logo 12 | 13 | 14 | ## Instructions 15 | 16 | ```bash 17 | $ npm i -g yo @pixel2html/generator-shopify 18 | $ yo @pixel2html/shopify 19 | ``` 20 | 21 | ## Features 22 | 23 | - Sourcemaps 24 | - JS with Webpack and ES6 (Just require your problems away) 25 | - Split vendor and app code (both JS and SCSS) 26 | - SVG System 27 | - Shopify Plus in mind (Checkout layouts) 28 | - Sensible starting points (all in blank but already wired up) 29 | - Based of Gulp 4 30 | - Live reloading with Browser Sync 31 | - Zip everything in the end 32 | -------------------------------------------------------------------------------- /src/app/index.js: -------------------------------------------------------------------------------- 1 | import Yeoman from 'yeoman-generator' 2 | import cowsay from 'cowsay-browser' 3 | import chalk from 'chalk' 4 | import filesToAssert from './lib/filesToAssert' 5 | import parrotSay from 'sync-parrot-api' 6 | 7 | import filter from 'gulp-filter' 8 | import prettify from 'gulp-jsbeautifier' 9 | import updateNotifier from 'update-notifier' 10 | 11 | const pkg = require('../../package.json') 12 | 13 | class ShopifySkeleton extends Yeoman { 14 | notify () { 15 | updateNotifier({pkg}).notify() 16 | } 17 | 18 | vaderSays () { 19 | const generalOverview = cowsay.say({ 20 | text: 'A few general purpose questions now...', 21 | f: 'vader' 22 | }) 23 | return this.log(chalk.red(generalOverview)) 24 | } 25 | 26 | mustHavePrompts () { 27 | return this.prompt([ 28 | { 29 | type: 'input', 30 | name: 'projectName', 31 | message: 'Name of your Project?' 32 | }, 33 | { 34 | type: 'confirm', 35 | name: 'npmInstall', 36 | message: 'Want me to run npm install after we\'re done?', 37 | default: false 38 | } 39 | ]) 40 | .then(props => { 41 | this.options.projectName = props.projectName 42 | this.options.npmInstall = props.npmInstall 43 | }) 44 | } 45 | 46 | suchTalk () { 47 | const dogeText = 'To set up a shop now you will need to have' + '\n' + 48 | 'private API credentials at hand see more here:' + '\n' + 49 | 'https://help.shopify.com/api/getting-started/api-credentials' 50 | const muchWow = cowsay.think({ 51 | text: dogeText, 52 | f: 'doge' 53 | }) 54 | return this.options.noAnims 55 | ? this.log(chalk.magenta(muchWow)) 56 | : this.log(chalk.hex('#b69a4e')(muchWow)) 57 | } 58 | 59 | setShopNowPrompt () { 60 | return this.prompt([ 61 | { 62 | type: 'confirm', 63 | name: 'setShopNow', 64 | message: 'Do you want to set up your shop credentials now?', 65 | default: true 66 | } 67 | ]) 68 | .then(props => { 69 | this.options.setShopNow = props.setShopNow 70 | }) 71 | } 72 | 73 | shopifyConfigs () { 74 | return this.options.setShopNow 75 | ? this.prompt([ 76 | { 77 | type: 'input', 78 | name: 'shopName', 79 | message: 'Shop Name (Its the part that goes before the .myshopify.com bit on the admin)' 80 | }, 81 | { 82 | type: 'input', 83 | name: 'shopKey', 84 | message: 'API Key' 85 | }, { 86 | type: 'input', 87 | name: 'shopPassword', 88 | message: 'Password' 89 | }, { 90 | type: 'input', 91 | name: 'shopSecret', 92 | message: 'Shared Secret' 93 | }, { 94 | type: 'input', 95 | name: 'shopThemeId', 96 | message: 'Theme ID (Create a new theme click customize HTML/CSS and its after the themes/ part on the URL)' 97 | } 98 | ]) 99 | .then(props => { 100 | this.options.shopName = props.shopName 101 | this.options.shopKey = props.shopKey 102 | this.options.shopPassword = props.shopPassword 103 | this.options.shopSecret = props.shopSecret 104 | this.options.shopThemeId = props.shopThemeId 105 | }) 106 | : false 107 | } 108 | 109 | copyShopifyCoreFiles () { 110 | const { 111 | projectName 112 | } = this.options 113 | const templates = { 114 | author: 'Pixel2HTML', 115 | projectName 116 | } 117 | return filesToAssert.shopifyCoreFiles.map(file => { 118 | this.fs.copyTpl( 119 | this.templatePath(`theme/${file}`), 120 | this.destinationPath(`src/theme/${file}`), 121 | templates 122 | ) 123 | }) 124 | } 125 | 126 | copyDotFiles () { 127 | const { 128 | projectName, 129 | shopName, 130 | shopKey, 131 | shopPassword, 132 | shopSecret, 133 | shopThemeId, 134 | setShopNow 135 | } = this.options 136 | 137 | const version = pkg.version 138 | 139 | const templates = { 140 | projectName, 141 | shopName, 142 | shopKey, 143 | shopPassword, 144 | shopSecret, 145 | shopThemeId, 146 | setShopNow, 147 | version 148 | } 149 | 150 | return filesToAssert.dotfiles.map(file => { 151 | this.fs.copyTpl( 152 | this.templatePath(`base/${file}`), 153 | this.destinationPath(`.${file}`), 154 | templates 155 | ) 156 | }) 157 | } 158 | 159 | copyBaseFiles () { 160 | const { 161 | projectName, 162 | shopName, 163 | shopKey, 164 | shopPassword, 165 | shopSecret, 166 | shopThemeId, 167 | setShopNow 168 | } = this.options 169 | 170 | const version = pkg.version 171 | 172 | const templates = { 173 | projectName: projectName.split(' ').join('-'), 174 | shopName, 175 | shopKey, 176 | shopPassword, 177 | shopSecret, 178 | shopThemeId, 179 | setShopNow, 180 | version 181 | } 182 | 183 | return filesToAssert.baseFiles.map(file => { 184 | this.fs.copyTpl( 185 | this.templatePath(`base/${file}`), 186 | this.destinationPath(file), 187 | templates 188 | ) 189 | }) 190 | } 191 | 192 | copyGulpFiles () { 193 | return filesToAssert.gulpFiles.map(file => { 194 | this.fs.copyTpl( 195 | this.templatePath(`gulp/${file}`), 196 | this.destinationPath(`gulp/${file}`), 197 | { 198 | author: 'Pixel2HTML' 199 | } 200 | ) 201 | }) 202 | } 203 | 204 | copyStaticFiles () { 205 | return filesToAssert.staticFiles.map(file => { 206 | this.fs.copyTpl( 207 | this.templatePath(file), 208 | this.destinationPath(`src/${file}`), 209 | { 210 | author: 'Pixel2HTML' 211 | } 212 | ) 213 | }) 214 | } 215 | 216 | install () { 217 | this.options.npmInstall 218 | ? this.npmInstall() 219 | : this.log('Skipping npm install') 220 | } 221 | 222 | eslintJs () { 223 | this.log('Pretty JS and JSON 🙌') 224 | const jsFilter = filter(['**/*.js', '**/*.json'], { restore: true }) 225 | this.registerTransformStream([ 226 | jsFilter, 227 | prettify({ 228 | indent_size: 2 229 | }), 230 | jsFilter.restore 231 | ]) 232 | } 233 | 234 | end () { 235 | const message = this.options.setShopNow 236 | ? 'Thank you and Good Luck!' 237 | : 'Remember to fill in the variables inside .env so gulp can run' 238 | this.options.noAnims 239 | ? this.log(chalk.white((message))) 240 | : this.log(parrotSay(message + ' 🦄')) 241 | this.log('PS: use npm run code to start') 242 | return this.log('Love, Pixel2HTML') 243 | } 244 | } 245 | 246 | export default ShopifySkeleton 247 | -------------------------------------------------------------------------------- /src/app/lib/clean.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra') 2 | const { DIST } = require('./directories') 3 | 4 | fs.remove(DIST) 5 | .then(() => { 6 | console.log('Success') 7 | }) 8 | .catch(err => { 9 | console.error(err) 10 | }) 11 | -------------------------------------------------------------------------------- /src/app/lib/copy.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra') 2 | const { SRC, DIST } = require('./directories') 3 | 4 | fs.copy(SRC, DIST) 5 | .then(() => { 6 | console.log('Success') 7 | }) 8 | .catch(err => { 9 | console.error(err) 10 | }) 11 | -------------------------------------------------------------------------------- /src/app/lib/directories.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const SRC = path.join(__dirname, '../../../src') 3 | const DIST = path.join(__dirname, '../../../generators') 4 | 5 | module.exports = { 6 | SRC, 7 | DIST 8 | } 9 | -------------------------------------------------------------------------------- /src/app/lib/filesToAssert.js: -------------------------------------------------------------------------------- 1 | const shopifyCoreFiles = [ 2 | // CONFIG 3 | 'config/settings_schema.json', 4 | // LAYOUT 5 | 'layout/checkout.liquid', 6 | 'layout/theme.liquid', 7 | // LOCALES 8 | 'locales/en.default.json', 9 | 'locales/es.json', 10 | // SECTIONS 11 | 'sections/featured-collection.liquid', 12 | // SNIPPETS 13 | 'snippets/svg-icons.liquid', 14 | // CUSTOMERS 15 | 'templates/customers/account.liquid', 16 | 'templates/customers/activate_account.liquid', 17 | 'templates/customers/addresses.liquid', 18 | 'templates/customers/login.liquid', 19 | 'templates/customers/order.liquid', 20 | 'templates/customers/register.liquid', 21 | 'templates/customers/reset_password.liquid', 22 | // TEMPLATES NORMAL 23 | 'templates/404.liquid', 24 | 'templates/article.liquid', 25 | 'templates/blog.liquid', 26 | 'templates/cart.liquid', 27 | 'templates/collection.liquid', 28 | 'templates/gift_card.liquid', 29 | 'templates/index.liquid', 30 | 'templates/list-collections.liquid', 31 | 'templates/page.contact.liquid', 32 | 'templates/page.liquid', 33 | 'templates/password.liquid', 34 | 'templates/product.liquid', 35 | 'templates/search.liquid' 36 | ] 37 | 38 | const dotfiles = [ 39 | 'env', 40 | 'env.example', 41 | 'gitignore' 42 | ] 43 | 44 | const baseFiles = [ 45 | 'LICENSE', 46 | 'editorconfig', 47 | 'gulpfile.js', 48 | 'package.json', 49 | 'readme.md', 50 | 'webpack.config.js' 51 | ] 52 | 53 | const gulpFiles = [ 54 | 'gulp.config.js', 55 | // Tasks 56 | 'tasks/clean.js', 57 | 'tasks/deploy.js', 58 | 'tasks/fonts.js', 59 | 'tasks/icons.js', 60 | 'tasks/images.js', 61 | 'tasks/scripts.js', 62 | 'tasks/serve.js', 63 | 'tasks/shopify.js', 64 | 'tasks/styles.js', 65 | 'tasks/watch.js', 66 | 'tasks/zip.js' 67 | ] 68 | 69 | const staticFiles = [ 70 | 'fonts/.gitkeep', 71 | 'icons/gulp.svg', 72 | 'images/shopify.svg', 73 | 'scripts/index.js', 74 | 'styles/main.scss', 75 | 'styles/vendor.scss' 76 | ] 77 | 78 | module.exports = { 79 | shopifyCoreFiles, 80 | baseFiles, 81 | gulpFiles, 82 | staticFiles, 83 | dotfiles 84 | } 85 | -------------------------------------------------------------------------------- /src/app/lib/mockPrompts.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | shopName: 'myCoolShop', 3 | shopKey: '40536c12bd360e76e8e7a36c10c02126', 4 | shopPassword: 'cd96664f9e1de0ce8393a42c18671ce2', 5 | shopSecret: 'a847d15aedc462f2f2e13070ff9d6b75', 6 | shopThemeId: '6929079' 7 | } 8 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/app/templates/base/env: -------------------------------------------------------------------------------- 1 | <% if (setShopNow) { -%> 2 | SHOP_NAME='<%= shopName %>' 3 | SHOP_KEY='<%= shopKey %>' 4 | SHOP_PASSWORD='<%= shopPassword %>' 5 | SHOP_SECRET='<%= shopSecret %>' 6 | SHOP_THEME_ID='<%= shopThemeId %>' 7 | <% } else {-%> 8 | SHOP_NAME='' 9 | SHOP_KEY='' 10 | SHOP_PASSWORD='' 11 | SHOP_SECRET='' 12 | SHOP_THEME_ID='' 13 | <% } -%> 14 | -------------------------------------------------------------------------------- /src/app/templates/base/env.example: -------------------------------------------------------------------------------- 1 | SHOP_NAME='' 2 | SHOP_KEY='' 3 | SHOP_PASSWORD='' 4 | SHOP_SECRET='' 5 | SHOP_THEME_ID='' 6 | -------------------------------------------------------------------------------- /src/app/templates/base/gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | dist/* 3 | .env 4 | dist 5 | releases 6 | .DS_Store 7 | settings_data.json 8 | -------------------------------------------------------------------------------- /src/app/templates/base/gulpfile.js: -------------------------------------------------------------------------------- 1 | const dotenv = require('dotenv') 2 | dotenv.config() 3 | 4 | const gulp = require('gulp') 5 | const requireDir = require('require-dir') 6 | 7 | requireDir('gulp', { 8 | recurse: true 9 | }) 10 | 11 | gulp.task('build', gulp.series( 12 | 'clean', 13 | 'fonts', 14 | 'icons', 15 | 'images', 16 | 'scripts', 17 | 'styles', 18 | 'shopify' 19 | )) 20 | 21 | gulp.task('release', gulp.series('build', 'zip')) 22 | 23 | gulp.task('serve', gulp.parallel( 24 | 'browser-sync', 25 | 'theme:init', 26 | 'theme:watch', 27 | 'watch' 28 | )) 29 | 30 | gulp.task('full-deploy', gulp.series('build', 'deploy')) 31 | 32 | gulp.task('default', gulp.series('build', 'serve')) 33 | -------------------------------------------------------------------------------- /src/app/templates/base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= projectName %>", 3 | "description": "Easy Scaffolding powered by Pixel2Html Shopify Skeleton", 4 | "license": "MIT", 5 | "repository": "http://www.pixel2html.com", 6 | "version": "1.0.0", 7 | "scripts": { 8 | "start": "npm install", 9 | "code": "cross-env NODE_ENV=development gulp", 10 | "release": "cross-env NODE_ENV=production gulp release", 11 | "build": "cross-env NODE_ENV=production gulp build", 12 | "deploy": "cross-env NODE_ENV=production gulp full-deploy", 13 | "kill-theme": "cross-env NODE_ENV=development gulp kill:theme", 14 | "webpack": "cross-env NODE_ENV=development webpack", 15 | "webpack:prod": "cross-env NODE_ENV=production webpack", 16 | "debug": "cross-env NODE_ENV=development cross-env DEBUG_MODE=true webpack", 17 | "debug:prod": "cross-env NODE_ENV=production cross-env DEBUG_MODE=true webpack", 18 | "lint:js": "eslint 'src/scripts/**/*.js'", 19 | "lint:scss": "stylelint 'src/styles/**/*.scss'", 20 | "lint": "npm run lint:js; npm run lint:scss" 21 | }, 22 | "dependencies": { 23 | "@babel/core": "^7.0.0-beta.38", 24 | "@babel/runtime": "^7.0.0-beta.38", 25 | "@pixel2html/babel-preset": "^0.7.0", 26 | "babel-loader": "8.0.0-beta.0", 27 | "cross-env": "^5.1.3", 28 | "del": "^3.0.0", 29 | "dotenv": "^4.0.0", 30 | "eslint-loader": "^1.9.0", 31 | "gulp": "^4.0.0", 32 | "gulp-autoprefixer": "^4.0.0", 33 | "gulp-changed-in-place": "^2.3.0", 34 | "gulp-concat": "^2.6.1", 35 | "gulp-csscomb": "^3.0.8", 36 | "gulp-cssnano": "^2.1.2", 37 | "gulp-flatten": "^0.3.1", 38 | "gulp-group-css-media-queries": "^1.2.0", 39 | "gulp-if": "^2.0.2", 40 | "gulp-load-plugins": "^1.5.0", 41 | "gulp-pug": "^3.3.0", 42 | "gulp-rename": "^1.2.2", 43 | "gulp-sass": "^3.1.0", 44 | "gulp-shopify-theme": "mike3run/gulp-shopify-theme", 45 | "gulp-sourcemaps": "^2.6.1", 46 | "gulp-svgmin": "^1.2.4", 47 | "gulp-svgstore": "^6.1.0", 48 | "gulp-uglify": "^3.0.0", 49 | "gulp-watch": "^4.3.11", 50 | "gulp-zip": "^4.0.0", 51 | "jquery": "^3.2.1", 52 | "require-dir": "^0.3.2", 53 | "sass-module-importer": "^1.4.0", 54 | "svg4everybody": "^2.1.9", 55 | "uglifyjs-webpack-plugin": "^1.1.4", 56 | "webpack": "^3.10.0" 57 | }, 58 | "devDependencies": { 59 | "@pixel2html/eslint-config": "^1.0.0", 60 | "@pixel2html/stylelint-config": "^1.3.0", 61 | "browser-sync": "^2.18.13", 62 | "eslint": "^4.14.0", 63 | "react-dev-utils": "^4.2.1", 64 | "stylelint": "^8.4.0", 65 | "webpack-bundle-analyzer": "^2.9.1", 66 | "webpack-monitor": "^1.0.14" 67 | }, 68 | "stylelint": { 69 | "extends": "@pixel2html/stylelint-config" 70 | }, 71 | "eslintConfig": { 72 | "extends": "@pixel2html/eslint-config" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/app/templates/base/readme.md: -------------------------------------------------------------------------------- 1 | # <%= projectName %> 2 | 3 | ## Scaffolded by Shopify Skeleton Version <%= version %> 4 | 5 | Easy Shopify Development 💅 6 | 7 | ## Important 8 | 9 | Your code will *not* compile unless you provide your Shopify API variables for the deploy task. 10 | Add them in the `.env` they will not be commited or shared this is for security reasons. 11 | 12 | 13 | ## Quick Start 14 | 15 | Compile things and auto upload to shopify 16 | 17 | ```bash 18 | $ npm run code 19 | ``` 20 | 21 | Zip everything and code in production mode 22 | 23 | ```bash 24 | $ npm run build 25 | ``` 26 | 27 | Full Deployment (useful with CI or during first time upload) 28 | 29 | ```bash 30 | $ npm run deploy 31 | ``` 32 | 33 | Delete Theme Files. Use with care!! (Good during first time upload) 34 | 35 | ```bash 36 | $ npm run kill-theme 37 | ``` 38 | 39 | ## Features 40 | 41 | - Sourcemaps 42 | - JS with Browserify and ES6 (Just require your problems away) 43 | - Split vendor and app code (both JS and CSS) 44 | - SVG System 45 | - Shopify Plus in mind (Checkout layouts) 46 | - Sensible starting points (all in blank but already wired up) 47 | - Based of Gulp 4 48 | - Live reloading with Browser Sync 49 | - Zip everything in the end 50 | 51 | -------------------------------------------------------------------------------- /src/app/templates/base/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin') 3 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 4 | const config = require('./gulp/gulp.config') 5 | const {cwd, env} = require('process') 6 | 7 | const production = config.production 8 | const debug = config.debug 9 | const WebpackMonitor = require('webpack-monitor') 10 | 11 | // When you really want to make the relationship work... 12 | const ENTRY_PATH = cwd() + '/' + config.src.scripts 13 | const OUTPUT_PATH = cwd() + '/' + config.theme + '/assets' 14 | 15 | let plugins = [ 16 | // Add the env to remove excess skin 17 | new webpack.DefinePlugin({ 18 | 'process.env': { 19 | NODE_ENV: JSON.stringify(env.NODE_ENV) 20 | } 21 | }), 22 | new webpack.SourceMapDevToolPlugin({ 23 | filename: '[name].js.map', 24 | append: '\n//# sourceMappingURL={{ "[url]" | asset_url }}', 25 | test: /\.(js|liquid)$/ 26 | }), 27 | // Add module names to factory functions so they appear in browser profiler. 28 | new webpack.NamedModulesPlugin(), 29 | // Allow everyone to use jQuery like it was global 30 | new webpack.ProvidePlugin({ 31 | $: 'jquery', 32 | jQuery: 'jquery', 33 | 'window.jQuery': 'jquery' 34 | }), 35 | // Separate node_modules packages 36 | new webpack.optimize.CommonsChunkPlugin({ 37 | name: 'vendor', 38 | minChunks: module => /node_modules/.test(module.resource) 39 | }), 40 | // Do NOT import the BLOAT from moment.js 41 | // thanks create-react-app 42 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) 43 | ] 44 | 45 | const productionPlugins = [ 46 | // Concatenate modules for smaller builds 47 | new webpack.optimize.ModuleConcatenationPlugin(), 48 | // Uglify the heck out of this 49 | new UglifyJSPlugin({ 50 | sourceMap: true, 51 | test: /\.(js|liquid)$/ 52 | }) 53 | ] 54 | 55 | const debugPlugins = [ 56 | new BundleAnalyzerPlugin(), 57 | new WebpackMonitor({ 58 | target: cwd() + '/gulp/stats.json', 59 | launch: true, 60 | port: 5000 61 | }) 62 | ] 63 | 64 | if (production) plugins = [...plugins, ...productionPlugins] 65 | if (debug) plugins = [...plugins, ...debugPlugins] 66 | 67 | const CONFIG = { 68 | entry: ENTRY_PATH, 69 | module: { 70 | rules: [ 71 | { 72 | test: /\.(js|jsx)$/, 73 | exclude: /node_modules/, 74 | enforce: 'pre', 75 | use: { 76 | loader: 'eslint-loader' 77 | } 78 | }, 79 | { 80 | test: /\.(js|jsx)$/, 81 | exclude: /node_modules/, 82 | use: { 83 | loader: 'babel-loader', 84 | options: { 85 | presets: [ 86 | require.resolve('@pixel2html/babel-preset') 87 | ], 88 | cacheDirectory: true 89 | } 90 | } 91 | } 92 | ] 93 | }, 94 | output: { 95 | filename: debug ? '[name].js' : '[name].js.liquid', 96 | path: OUTPUT_PATH 97 | }, 98 | plugins, 99 | externals: { 100 | jquery: 'jQuery' 101 | }, 102 | // Some libraries import Node modules but don't use them in the browser. 103 | // Tell Webpack to provide empty mocks for them so importing them works. 104 | node: { 105 | dgram: 'empty', 106 | fs: 'empty', 107 | net: 'empty', 108 | tls: 'empty', 109 | child_process: 'empty' 110 | } 111 | } 112 | 113 | module.exports = CONFIG 114 | -------------------------------------------------------------------------------- /src/app/templates/fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/fonts/.gitkeep -------------------------------------------------------------------------------- /src/app/templates/gulp/gulp.config.js: -------------------------------------------------------------------------------- 1 | // We use this to read flags in the command line 2 | const production = process.env.NODE_ENV === 'production' 3 | const debug = process.env.DEBUG_MODE === 'true' 4 | 5 | module.exports = { 6 | theme: 'dist', 7 | shopify: { 8 | key: process.env.SHOP_KEY, 9 | pass: process.env.SHOP_PASSWORD, 10 | secret: process.env.SHOP_SECRET, 11 | themeId: process.env.SHOP_THEME_ID, 12 | shopName: process.env.SHOP_NAME, 13 | flatFolders: [ 14 | 'assets', 15 | 'config', 16 | 'layout', 17 | 'locales', 18 | 'templates' 19 | ], 20 | multiLevelFolders: [ 21 | 'sections', 22 | 'snippets' 23 | ] 24 | }, 25 | src: { 26 | styles: './src/styles', 27 | scripts: 'src/scripts', 28 | fonts: [ 29 | './src/fonts/**/*' 30 | ], 31 | icons: [ 32 | './src/icons/**/*' 33 | ], 34 | images: [ 35 | './src/images/**/*.{svg,png,jpg,jpeg,gif,ico}' 36 | ], 37 | shopify: [ 38 | './src/theme/**/*' 39 | ], 40 | theme: './src/theme' 41 | }, 42 | onError: function (error) { 43 | console.log(error.toString()) 44 | production 45 | ? process.exit(1) 46 | : this.emit('end') 47 | }, 48 | production, 49 | debug, 50 | // For autoprefixer 51 | browsers: [ 52 | 'last 2 Chrome versions', 53 | 'last 2 ChromeAndroid versions', 54 | 'last 2 Firefox versions', 55 | 'last 2 Safari versions', 56 | 'last 2 ios versions', 57 | 'last 1 ie versions', 58 | 'last 2 Edge versions', 59 | 'last 2 Opera versions' 60 | ], 61 | appendLiquidExt: path => { 62 | if (path.extname === '.map') return 63 | if (path.extname === '.css') { 64 | path.extname = '.scss' 65 | } 66 | path.basename += path.extname 67 | path.extname = '.liquid' 68 | }, 69 | makeLiquidSourceMappingURL: file => `{{ "${file.relative}.map" | asset_url }}`, 70 | flatten: path => { 71 | if (path.dirname !== '.') { 72 | path.basename = path.dirname.replace('/', '_') + '_' + path.basename 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/clean.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const del = require('del') 4 | 5 | gulp.task('clean', function () { 6 | return del([config.theme, 'releases']) 7 | }) 8 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/deploy.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const watch = require('gulp-watch') 3 | const config = require('../gulp.config') 4 | const shopify = require('gulp-shopify-theme') 5 | const theme = shopify.create() 6 | 7 | const browserSync = require('browser-sync') 8 | 9 | const reload = () => { 10 | browserSync.reload() 11 | } 12 | 13 | const shopifyConfig = { 14 | api_key: config.shopify.key, 15 | password: config.shopify.pass, 16 | shared_secret: config.shopify.secret, 17 | shop_name: config.shopify.shopName, 18 | theme_id: config.shopify.themeId 19 | } 20 | 21 | const validKeys = Object.keys(shopifyConfig).filter(key => shopifyConfig[key]) 22 | const CAN_DEPLOY = validKeys.length > 0 23 | 24 | const themeFiles = config.theme + '/{assets,layout,config,snippets,templates,locales,sections}/**/*' 25 | 26 | gulp.task('theme:init', done => { 27 | if (CAN_DEPLOY) theme.init(shopifyConfig) 28 | done() 29 | }) 30 | 31 | gulp.task('theme:watch', done => 32 | CAN_DEPLOY 33 | ? watch(themeFiles, {verbose: true}) 34 | .pipe(theme.stream(undefined, () => { 35 | reload() 36 | done() 37 | })).on('error', config.onError) 38 | : done() 39 | ) 40 | 41 | gulp.task('theme:upload', () => CAN_DEPLOY 42 | ? gulp.src(themeFiles) 43 | .pipe(theme.stream()) 44 | .on('error', config.onError) 45 | : null 46 | ) 47 | 48 | gulp.task('deploy', gulp.series('theme:init', 'theme:upload')) 49 | 50 | // Danger Zone 💀 51 | gulp.task('theme:purge', function (done) { 52 | theme.purge() 53 | done() 54 | }) 55 | gulp.task('kill:theme', gulp.series('theme:init', 'theme:purge')) 56 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/fonts.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | 4 | gulp.task('fonts', function () { 5 | return gulp.src(config.src.fonts) 6 | .pipe(gulp.dest(config.theme + '/assets')) 7 | }) 8 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/icons.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const $ = require('gulp-load-plugins')() 4 | 5 | gulp.task('icons', function () { 6 | return gulp.src(config.src.icons) 7 | .pipe($.svgmin({ 8 | plugins: [ 9 | { 10 | removeStyleElement: true 11 | }, 12 | { 13 | removeAttrs: { 14 | attrs: ['fill', 'stroke', 'fill.*', 'stroke.*'] 15 | } 16 | } 17 | ], 18 | js2svg: { pretty: true } 19 | })) 20 | .pipe($.svgstore({inlineSvg: true})) 21 | .pipe($.rename('svg-icons.liquid')) 22 | .pipe(gulp.dest(config.theme + '/snippets')) 23 | }) 24 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/images.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const $ = require('gulp-load-plugins')() 4 | 5 | gulp.task('images', () => 6 | gulp.src(config.src.images) 7 | .pipe($.changedInPlace({ firstPass: true })) 8 | .pipe($.rename(config.flatten)) 9 | .pipe($.rename({ dirname: '', prefix: '' })) 10 | .pipe(gulp.dest(config.theme + '/assets')) 11 | ) 12 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/scripts.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const webpack = require('webpack') 3 | const webpackConfig = require('../../webpack.config') 4 | const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages') 5 | 6 | gulp.task('scripts', () => 7 | new Promise(resolve => webpack(webpackConfig, (err, stats) => { 8 | if (err) console.log('Webpack', err) 9 | var rawMessages = stats.toJson({}, true) 10 | var messages = formatWebpackMessages(rawMessages) 11 | if (!messages.errors.length && !messages.warnings.length) { 12 | console.log(stats.toString({ 13 | chunks: false, 14 | colors: true 15 | })) 16 | } 17 | if (messages.errors.length) { 18 | console.log('Failed to compile.') 19 | messages.errors.forEach(e => console.log(e)) 20 | resolve() 21 | } 22 | if (messages.warnings.length) { 23 | console.log('Compiled with warnings.') 24 | messages.warnings.forEach(w => console.log(w)) 25 | } 26 | resolve() 27 | })) 28 | ) 29 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/serve.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const browserSync = require('browser-sync') 4 | const WebpackDevServerUtils = require('react-dev-utils/WebpackDevServerUtils') 5 | const {choosePort} = WebpackDevServerUtils 6 | 7 | const DEFAULT_PORT = 3000 8 | const HOST = '0.0.0.0' 9 | 10 | gulp.task('browser-sync', done => { 11 | choosePort(HOST, DEFAULT_PORT) 12 | .then(port => { 13 | if (port === null) { 14 | return 15 | } 16 | browserSync.init({ 17 | port, 18 | open: true, 19 | logConnections: true, 20 | logPrefix: 'Pixel2Html', 21 | proxy: `https://${config.shopify.shopName}.myshopify.com`, 22 | startPath: `?preview_theme_id=${config.shopify.themeId}`, 23 | reloadDebounce: 2000 24 | }) 25 | done() 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/shopify.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const $ = require('gulp-load-plugins')() 4 | 5 | const createShopifyTask = name => { 6 | gulp.task(`shopify:${name}`, () => 7 | gulp.src(config.src.theme + `/${name}/**/*`) 8 | .pipe($.changedInPlace({firstPass: true})) 9 | .pipe(gulp.dest(config.theme + `/${name}`)) 10 | ) 11 | } 12 | 13 | const flattenShopifyTask = name => { 14 | gulp.task(`shopify:${name}`, () => 15 | gulp.src(config.src.theme + `/${name}/**/*`) 16 | .pipe($.changedInPlace({firstPass: true})) 17 | .pipe($.flatten()) 18 | .pipe(gulp.dest(config.theme + `/${name}`)) 19 | ) 20 | } 21 | 22 | config.shopify.flatFolders.forEach(createShopifyTask) 23 | config.shopify.multiLevelFolders.forEach(flattenShopifyTask) 24 | 25 | const allFolders = [ 26 | ...config.shopify.flatFolders, 27 | ...config.shopify.multiLevelFolders 28 | ] 29 | 30 | const shopifyTaskNames = allFolders.map(folder => `shopify:${folder}`) 31 | 32 | gulp.task('shopify', gulp.parallel(...shopifyTaskNames)) 33 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/styles.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const when = require('gulp-if') 4 | const $ = require('gulp-load-plugins')() 5 | const production = config.production 6 | const moduleImporter = require('sass-module-importer') 7 | 8 | const destination = config.theme + '/assets' 9 | 10 | gulp.task('main:styles', function () { 11 | return gulp.src(config.src.styles + '/main.scss') 12 | .pipe(when(!production, $.sourcemaps.init())) 13 | .pipe($.sass({importer: moduleImporter()})) 14 | .on('error', $.sass.logError) 15 | .pipe($.autoprefixer({browsers: config.browsers})) 16 | .pipe(when(production, $.groupCssMediaQueries())) 17 | .pipe(when(production, $.csscomb())) 18 | .pipe(when(!production, $.sourcemaps.write('.', {sourceMappingURL: config.makeLiquidSourceMappingURL}))) 19 | .pipe(when(production, $.cssnano())) 20 | .pipe($.rename(config.appendLiquidExt)) // main.css.liquid 21 | .pipe(gulp.dest(destination)) 22 | }) 23 | 24 | gulp.task('vendor:styles', function () { 25 | return gulp.src(config.src.styles + '/vendor.scss') 26 | .pipe(when(!production, $.sourcemaps.init())) 27 | .pipe($.sass({importer: moduleImporter()})) 28 | .on('error', $.sass.logError) 29 | .pipe($.autoprefixer({browsers: config.browsers})) 30 | .pipe(when(production, $.groupCssMediaQueries())) 31 | .pipe(when(production, $.csscomb())) 32 | .pipe(when(!production, $.sourcemaps.write('.', {sourceMappingURL: config.makeLiquidSourceMappingURL}))) 33 | .pipe(when(production, $.cssnano())) 34 | .pipe($.rename(config.appendLiquidExt)) // vendor.css.liquid 35 | .pipe(gulp.dest(destination)) 36 | }) 37 | 38 | gulp.task('styles', gulp.parallel('main:styles', 'vendor:styles')) 39 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/watch.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | 4 | const createShopifyWatchTask = name => { 5 | gulp.watch(config.src.theme + `/${name}/**/*`, gulp.series(`shopify:${name}`)) 6 | } 7 | const SHOPIFY_FOLDERS = [ 8 | ...config.shopify.flatFolders, 9 | ...config.shopify.multiLevelFolders 10 | ] 11 | 12 | gulp.task('watch', done => { 13 | gulp.watch(config.src.fonts, gulp.series('fonts')) 14 | gulp.watch(config.src.icons, gulp.series('icons')) 15 | gulp.watch(config.src.images, gulp.series('images')) 16 | gulp.watch(config.src.scripts + '/**/*', gulp.series('scripts')) 17 | gulp.watch(config.src.styles + '/**/*', gulp.series('styles')) 18 | SHOPIFY_FOLDERS.forEach(createShopifyWatchTask) 19 | done() 20 | }) 21 | -------------------------------------------------------------------------------- /src/app/templates/gulp/tasks/zip.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const config = require('../gulp.config') 3 | const zip = require('gulp-zip') 4 | const pkg = require('../../package.json') 5 | const version = pkg.version 6 | const zipName = `v.${version} - MASTER.zip` 7 | 8 | const openBrowser = require('react-dev-utils/openBrowser') 9 | 10 | const distFiles = [ 11 | `${config.theme}/**`, 12 | `!${config.theme}` 13 | ] 14 | 15 | gulp.task('zip', () => 16 | gulp.src(distFiles, {base: '.'}) 17 | .pipe(zip(zipName)).on('error', config.onError) 18 | .pipe(gulp.dest('releases')) 19 | ) 20 | 21 | gulp.task('openBrowser', done => { 22 | openBrowser(`https://${config.shopify.shopName}.myshopify.com/admin/themes`) 23 | done() 24 | }) 25 | -------------------------------------------------------------------------------- /src/app/templates/icons/gulp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/app/templates/images/shopify.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/app/templates/scripts/index.js: -------------------------------------------------------------------------------- 1 | // EXAMPLE DELETE EVERYTHING BELOW 2 | // Learn more about ES6 Here: 3 | // http://wesbos.com/javascript-modules/ 4 | // https://babeljs.io/learn-es2015/ 5 | 6 | const colors = [ 'pink', 'red', 'blue' ] 7 | const moColors = ['blue', 'orange'] 8 | 9 | // We have Es6 Goodies thanks to Babel 10 | const allTheColors = [ ...colors, ...moColors ] 11 | allTheColors.map(c => console.log(c)) 12 | -------------------------------------------------------------------------------- /src/app/templates/styles/main.scss: -------------------------------------------------------------------------------- 1 | .is-hidden { 2 | position: absolute; 3 | height: 0; 4 | width: 0; 5 | visibility: hidden; 6 | } 7 | 8 | svg[class^="icon-"] { 9 | fill: currentColor; 10 | stroke: none; 11 | max-width: 100%; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/templates/styles/vendor.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/styles/vendor.scss -------------------------------------------------------------------------------- /src/app/templates/theme/config/settings_schema.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "theme_info", 4 | "logo": "https:\/\/cdn.shopify.com\/s\/global\/branding\/shopify_logo_256x256.png", 5 | "settings": [ 6 | { 7 | "type": "header", 8 | "content": "<%= projectName %>" 9 | }, 10 | { 11 | "type": "paragraph", 12 | "content": "Scaffolded with Pixel2HTML's Shopify Skeleton" 13 | } 14 | ] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /src/app/templates/theme/layout/checkout.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= projectName %> 9 | {% if page_description %} {% endif %} 10 | 11 | 12 | {{ checkout_stylesheets }} 13 | {{ 'fonts.css' | asset_url | stylesheet_tag }} 14 | {{ 'vendor.css' | asset_url | stylesheet_tag }} 15 | {{ 'main.css' | asset_url | stylesheet_tag }} 16 | {{ content_for_header }} 17 | 18 | 19 | 20 | 21 | 22 | {{ content_for_order_summary }} 23 | {{ content_for_layout }} 24 | 25 | {{ "vendor.js" | asset_url | script_tag }} 26 | {{ "app.js" | asset_url | script_tag }} 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/app/templates/theme/layout/theme.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= projectName %> 9 | {% if page_description %} {% endif %} 10 | 11 | 12 | 13 | {{ 'vendor.scss' | asset_url | stylesheet_tag }} 14 | {{ 'main.scss' | asset_url | stylesheet_tag }} 15 | {{ content_for_header }} 16 | 17 | 18 | 19 | 20 | 21 | {{ content_for_layout }} 22 | {{ "https://code.jquery.com/jquery-3.2.1.min.js" | script_tag }} 23 | {{ "vendor.js" | asset_url | script_tag }} 24 | {{ "main.js" | asset_url | script_tag }} 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/app/templates/theme/locales/en.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "cart": { 3 | "remove": "Remove", 4 | "update": "Update" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/templates/theme/locales/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "cart": { 3 | "remove": "Remover", 4 | "update": "Actualizar" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/templates/theme/sections/featured-collection.liquid: -------------------------------------------------------------------------------- 1 | {% if section.settings.title != blank %} 2 |

{{ section.settings.title | escape }}

3 | {% endif %} 4 | 5 | {%- assign collection = collections[section.settings.collection] -%} 6 | 7 | {% for product in collection.products limit: 6 %} 8 | 9 | {{ product.featured_image.src | img_url: '480x480' | img_tag: product.title }} 10 |

{{ product.title }}

11 |
12 | 13 |

14 | {% if product.compare_at_price > product.price %} 15 | 16 | {% if product.price_varies %} 17 | {%- assign sale_price = product.price | money -%} 18 | {{ 'products.product.on_sale_from_html' | t: price: sale_price }} 19 | {% else %} 20 | {{ 'products.product.on_sale' | t }} 21 | {{ product.price | money }} 22 | {% endif %} 23 | 24 | {% else %} 25 | 26 | {% if product.price_varies %} 27 | {%- assign price = product.price | money -%} 28 | {{ 'products.product.from_text_html' | t: price: price }} 29 | {% else %} 30 | {{ product.price | money }} 31 | {% endif %} 32 | 33 | {% endif %} 34 |

35 | {% else %} 36 | 37 | {% for i in (1..6) %} 38 | 39 | {% capture current %}{% cycle 1, 2, 3, 4, 5, 6 %}{% endcapture %} 40 | {{ 'product-' | append: current | placeholder_svg_tag: 'placeholder-svg placeholder-svg--small' }} 41 | 42 |

43 | {{ 'homepage.onboarding.product_title' | t }} 44 |

45 |
46 | 47 |

{{ 1999 | money }}

48 | {% endfor %} 49 | {% endfor %} 50 | 51 | {% schema %} 52 | { 53 | "name": "Featured collection", 54 | "settings": [ 55 | { 56 | "type": "text", 57 | "id": "title", 58 | "label": "Heading", 59 | "default": "Featured collection" 60 | }, 61 | { 62 | "id": "collection", 63 | "type": "collection", 64 | "label": "Collection" 65 | } 66 | ], 67 | "presets": [ 68 | { 69 | "name": "Featured collection", 70 | "category": "Collection" 71 | } 72 | ] 73 | } 74 | {% endschema %} 75 | -------------------------------------------------------------------------------- /src/app/templates/theme/snippets/svg-icons.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/snippets/svg-icons.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/404.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/404.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/article.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/article.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/blog.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/blog.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/cart.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/cart.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/collection.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/collection.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/customers/account.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/customers/account.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/customers/activate_account.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/customers/activate_account.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/customers/addresses.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/customers/addresses.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/customers/login.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/customers/login.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/customers/order.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/customers/order.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/customers/register.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/customers/register.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/customers/reset_password.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/customers/reset_password.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/gift_card.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/gift_card.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/index.liquid: -------------------------------------------------------------------------------- 1 |

Pixel2HTML Shopify Skeleton

2 |

<%= projectName %>

3 |

Change stuff and fly away

4 | -------------------------------------------------------------------------------- /src/app/templates/theme/templates/list-collections.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/list-collections.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/page.contact.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/page.contact.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/page.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/page.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/password.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/password.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/product.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/product.liquid -------------------------------------------------------------------------------- /src/app/templates/theme/templates/search.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixel2HTML/shopify-skeleton/69dc28da66617e89b550ddce3a22c3b929cf5d44/src/app/templates/theme/templates/search.liquid --------------------------------------------------------------------------------