@madebyseed/seed-cli-tools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,93 @@
1
+ const gulp = require('gulp');
2
+ const plumber = require('gulp-plumber');
3
+ const chokidar = require('chokidar');
4
+ const vinylPaths = require('vinyl-paths');
5
+ const del = require('del');
6
+ const size = require('gulp-size');
7
+
8
+ const config = require('./includes/config.js');
9
+ const utils = require('./includes/utilities.js');
10
+ const messages = require('./includes/messages.js');
11
+
12
+ const assetsPaths = [
13
+ config.src.assets,
14
+ config.src.templates,
15
+ config.src.sections,
16
+ config.src.snippets,
17
+ config.src.locales,
18
+ config.src.config,
19
+ config.src.layout,
20
+ ];
21
+
22
+ /**
23
+ * Copies assets to the `/dist` directory
24
+ *
25
+ * @param {Array} files
26
+ * @returns {Stream}
27
+ * @private
28
+ */
29
+ function processAssets(files) {
30
+ messages.logProcessFiles('build:assets');
31
+ return gulp.src(files, {base: config.src.root})
32
+ .pipe(plumber(utils.errorHandler))
33
+ .pipe(size({
34
+ showFiles: true,
35
+ pretty: true,
36
+ }))
37
+ .pipe(gulp.dest(config.dist.root));
38
+ }
39
+
40
+ /**
41
+ * Deletes specified files
42
+ *
43
+ * @param {Array} files
44
+ * @returns {Stream}
45
+ * @private
46
+ */
47
+ function removeAssets(files) {
48
+ messages.logProcessFiles('remove:assets');
49
+
50
+ const mapFiles = files.map((file) => {
51
+ const distFile = file.replace(config.src.root, config.dist.root);
52
+ return distFile;
53
+ });
54
+
55
+ return gulp.src(mapFiles)
56
+ .pipe(plumber(utils.errorHandler))
57
+ .pipe(vinylPaths(del))
58
+ .pipe(size({
59
+ showFiles: true,
60
+ pretty: true,
61
+ }));
62
+ }
63
+
64
+ /**
65
+ * Copies assets to the `/dist` directory
66
+ *
67
+ * @function build:assets
68
+ * @memberof seed-cli.tasks.build
69
+ * @static
70
+ */
71
+ gulp.task('build:assets', () => {
72
+ return processAssets(assetsPaths);
73
+ });
74
+
75
+ /**
76
+ * Watches assets in the `/src` directory
77
+ *
78
+ * @function watch:assets
79
+ * @memberof seed-cli.tasks.watch
80
+ * @static
81
+ */
82
+ gulp.task('watch:assets', () => {
83
+ const eventCache = utils.createEventCache();
84
+
85
+ chokidar.watch(assetsPaths, {
86
+ ignored: /(^|[/\\])\../,
87
+ ignoreInitial: true,
88
+ }).on('all', (event, path) => {
89
+ messages.logFileEvent(event, path);
90
+ eventCache.addEvent(event, path);
91
+ utils.processCache(eventCache, processAssets, removeAssets);
92
+ });
93
+ });
@@ -0,0 +1,54 @@
1
+ const gulp = require('gulp');
2
+ const sass = require('gulp-sass')(require('sass'));
3
+ const postcss = require('gulp-postcss');
4
+ const cssimport = require('gulp-cssimport');
5
+ const plumber = require('gulp-plumber');
6
+ const chokidar = require('chokidar');
7
+
8
+
9
+ const config = require('./includes/config.js');
10
+ // const utils = require('./includes/utilities.js');
11
+ const messages = require('./includes/messages.js');
12
+
13
+
14
+ /**
15
+ * Concatenate css via gulp-cssimport and copys to the `/dist` folder
16
+ *
17
+ * @param {Array} files
18
+ * @returns {Stream}
19
+ * @private
20
+ */
21
+ function processCss() {
22
+ return gulp.src(config.roots.css)
23
+ .pipe(plumber())
24
+ .pipe(sass().on('error', sass.logError))
25
+ .pipe(postcss(config.plugins.postcss))
26
+ .pipe(cssimport())
27
+ .pipe(gulp.dest(config.dist.assets));
28
+ }
29
+
30
+ /**
31
+ * Concatenate css via gulp-cssimport
32
+ *
33
+ * @function build:css
34
+ * @memberof seed-cli.tasks.build
35
+ * @static
36
+ */
37
+ gulp.task('build:css', () => {
38
+ return processCss();
39
+ });
40
+
41
+ /**
42
+ * Watches css in the `/src` directory
43
+ *
44
+ * @function watch:css
45
+ * @memberof seed-cli.tasks.watch
46
+ * @static
47
+ */
48
+ gulp.task('watch:css', () => {
49
+ chokidar.watch(config.src.css, {ignoreInitial: true})
50
+ .on('all', (event, path) => {
51
+ messages.logFileEvent(event, path)
52
+ processCss();
53
+ });
54
+ });
@@ -0,0 +1,53 @@
1
+ const gulp = require('gulp');
2
+ const uglify = require('gulp-uglify');
3
+ const include = require('gulp-include');
4
+ const plumber = require('gulp-plumber');
5
+ const chokidar = require('chokidar');
6
+
7
+ const config = require('./includes/config.js');
8
+ const messages = require('./includes/messages.js');
9
+ // const utils = require('./includes/utilities.js');
10
+
11
+ function processThemeJs() {
12
+ messages.logProcessFiles('build:js');
13
+ return gulp.src([config.roots.js, `!${config.roots.vendorJs}`])
14
+ .pipe(plumber())
15
+ .pipe(include())
16
+ .pipe(gulp.dest(config.dist.assets));
17
+ }
18
+
19
+ function processVendorJs() {
20
+ messages.logProcessFiles('build:vendor-js');
21
+ return gulp.src(config.roots.vendorJs)
22
+ .pipe(plumber())
23
+ .pipe(include())
24
+ .pipe(uglify({
25
+ mangle: true,
26
+ compress: true,
27
+ }))
28
+ .pipe(gulp.dest(config.dist.assets));
29
+ }
30
+
31
+ gulp.task('build:js', () => {
32
+ return processThemeJs();
33
+ });
34
+
35
+ gulp.task('watch:js', () => {
36
+ chokidar.watch([config.src.js, `!${config.roots.vendorJs}`, `!${config.src.vendorJs}`], {ignoreInitial: true})
37
+ .on('all', (event, path) => {
38
+ messages.logFileEvent(event, path);
39
+ processThemeJs();
40
+ });
41
+ });
42
+
43
+ gulp.task('build:vendor-js', () => {
44
+ return processVendorJs();
45
+ });
46
+
47
+ gulp.task('watch:vendor-js', () => {
48
+ chokidar.watch([config.roots.vendorJs, config.src.vendorJs], {ignoreInitial: true})
49
+ .on('all', (event, path) => {
50
+ messages.logFileEvent(event, path);
51
+ processVendorJs();
52
+ });
53
+ });
@@ -0,0 +1,89 @@
1
+ const gulp = require('gulp');
2
+ const vinylPaths = require('vinyl-paths');
3
+ const del = require('del');
4
+ const size = require('gulp-size');
5
+ const chokidar = require('chokidar');
6
+ const svgmin = require('gulp-svgmin');
7
+ const cheerio = require('gulp-cheerio');
8
+ const extReplace = require('gulp-ext-replace');
9
+ const plumber = require('gulp-plumber');
10
+
11
+ const config = require('./includes/config.js');
12
+ const utils = require('./includes/utilities.js');
13
+ const messages = require('./includes/messages.js');
14
+
15
+ /**
16
+ * Processing for SVGs prior to deployment - adds accessibility markup, and converts
17
+ * the file to a liquid snippet.
18
+ *
19
+ * @param {String|Array} files - glob/array of files to match & send to the stream
20
+ * @returns {Stream}
21
+ * @private
22
+ */
23
+ function processIcons(files) {
24
+ messages.logProcessFiles('build:svg');
25
+ return gulp.src(files)
26
+ .pipe(plumber(utils.errorHandler))
27
+ .pipe(svgmin())
28
+ .pipe(cheerio(config.plugins.cheerio))
29
+ .pipe(extReplace('.liquid'))
30
+ .pipe(size({
31
+ showFiles: true,
32
+ pretty: true,
33
+ }))
34
+ .pipe(gulp.dest(config.dist.snippets));
35
+ }
36
+
37
+ /**
38
+ * Cleanup/remove liquid snippets from the `dist` directory during watch tasks if
39
+ * any underlying SVG files in the `src` folder have been removed.
40
+ *
41
+ * @param {String|Array} files - glob/array of files to match & send to the stream
42
+ * @returns {Stream}
43
+ * @private
44
+ */
45
+ function removeIcons(files) {
46
+ messages.logProcessFiles('remove:svg');
47
+ const mapFiles = files.map((file) => {
48
+ const distFile = file.replace('src/icons', 'dist/snippets');
49
+ const snippetFile = distFile.replace('.svg', '.liquid');
50
+ return snippetFile;
51
+ });
52
+
53
+ return gulp.src(mapFiles)
54
+ .pipe(plumber(utils.errorHandler))
55
+ .pipe(vinylPaths(del))
56
+ .pipe(size({
57
+ showFiles: true,
58
+ pretty: true,
59
+ }));
60
+ }
61
+
62
+ /**
63
+ * Pre-processing for svg icons
64
+ *
65
+ * @function build:svg
66
+ * @memberof slate-cli.tasks.build
67
+ * @static
68
+ */
69
+ gulp.task('build:svg', () => {
70
+ return processIcons(config.src.icons);
71
+ });
72
+
73
+ /**
74
+ * Watches source svg icons for changes...
75
+ *
76
+ * @function watch:svg
77
+ * @memberof slate-cli.tasks.watch
78
+ * @static
79
+ */
80
+ gulp.task('watch:svg', () => {
81
+ const cache = utils.createEventCache();
82
+
83
+ chokidar.watch([config.src.icons], {ignoreInitial: true})
84
+ .on('all', (event, path) => {
85
+ messages.logFileEvent(event, path);
86
+ cache.addEvent(event, path);
87
+ utils.processCache(cache, processIcons, removeIcons);
88
+ });
89
+ });
@@ -0,0 +1,37 @@
1
+ const gulp = require('gulp');
2
+ const del = require('del');
3
+ const zip = require('gulp-zip');
4
+ const size = require('gulp-size');
5
+ const plumber = require('gulp-plumber');
6
+
7
+ const config = require('./includes/config.js');
8
+ const utils = require('./includes/utilities.js');
9
+
10
+ /**
11
+ * Clean up build dirs/files whenever doing a full/clean (re)build.
12
+ *
13
+ * @function build:clean
14
+ * @memberof slate-cli.tasks.build
15
+ * @static
16
+ */
17
+ gulp.task('clean', () => {
18
+ return del(['upload', 'dist']);
19
+ });
20
+
21
+ /**
22
+ * Compress theme and build a shopify-compatible `.zip` file for uploading to store
23
+ *
24
+ * @function compress
25
+ * @memberof slate-cli.tasks.deploy
26
+ * @static
27
+ */
28
+ gulp.task('compress', () => {
29
+ const distFiles = `${config.dist.root}**/*`;
30
+ const ignoreConfig = `!${config.dist.root}config.yml`;
31
+
32
+ return gulp.src([distFiles, ignoreConfig])
33
+ .pipe(plumber(utils.errorHandler))
34
+ .pipe(zip(`${config.packageJson.name}.zip` || 'theme.zip'))
35
+ .pipe(size({showFiles: true, pretty: true}))
36
+ .pipe(gulp.dest('./upload/'));
37
+ });
@@ -0,0 +1,15 @@
1
+ const gulp = require('gulp');
2
+ const utils = require('./includes/utilities.js');
3
+
4
+ /**
5
+ * Initiates shopify's cli command 'shopify theme push' on the dist folder,
6
+ * pushing it to stores theme
7
+ *
8
+ * @function deploy:dist
9
+ * @memberof seed-cli.tasks.deploy
10
+ * @static
11
+ */
12
+ gulp.task('deploy:dist', () => {
13
+ console.log("Running Shopify theme push on ./dist...")
14
+ return utils.deployDist();
15
+ })
@@ -0,0 +1,95 @@
1
+ const join = require('path').join;
2
+ const logger = require('debug')('seed-tools');
3
+ const findRoot = require('find-root');
4
+ const autoprefixer = require('autoprefixer');
5
+ const tailwindcss = require('tailwindcss');
6
+ const argv = require('minimist')(process.argv.slice(2));
7
+ const themeRoot = findRoot(process.cwd());
8
+
9
+ let pkg = {};
10
+
11
+ try {
12
+ pkg = require(join(themeRoot, 'package.json'));
13
+ } catch (err) {
14
+ logger(err);
15
+ }
16
+
17
+ /**
18
+ * seed-cli configuration object
19
+ * ## Markdown stuff
20
+ *
21
+ * It's a big description written in `markdown`
22
+ *
23
+ * Example:
24
+ *
25
+ * ```javascript
26
+ * $('something')
27
+ * .something(else);
28
+ * ```
29
+ *
30
+ * @namespace config
31
+ * @memberof seed-cli
32
+ * @summary Configuring seed-cli
33
+ * @prop {String} environment - development | staging | production
34
+ * @prop {String} tkconfig - path to themekit config file
35
+ * @prop {String} scssLintConfig - path to scss-lint config file
36
+ * @prop {String} deployLog - path to deploy log file
37
+ * @prop {String} src - globs (multi-filename matching patterns) for various source files
38
+ * @prop {Object} dist - paths to relevant folder locations in the distributable directory
39
+ * @prop {Object} roots - array of "root" (entry point) JS & CSS files
40
+ * @prop {Object} plugins - configuration objects passed to various plugins used in the task interface
41
+ */
42
+ const config = {
43
+ environment: argv.enviroment || 'development',
44
+ themeRoot,
45
+ packageJson: pkg,
46
+
47
+ tkConfig: 'config.yml',
48
+ deployLog: 'deploy.log',
49
+
50
+ src: {
51
+ root: 'src/',
52
+ js: 'src/scripts/**/*.{js,js.liquid}',
53
+ vendorJs: 'src/scripts/vendor/*.js',
54
+ json: 'src/**/*.json',
55
+ css: 'src/styles/**/*.{css,scss,scss.liquid}',
56
+ cssLint: 'src/styles/**/*.{css,scss}',
57
+ vendorCss: 'src/styles/vendor/*.{css,scss}',
58
+ assets: 'src/assets/**/*',
59
+ icons: 'src/icons/**/*.svg',
60
+ templates: 'src/templates/**/*',
61
+ snippets: 'src/snippets/*',
62
+ sections: 'src/sections/*',
63
+ locales: 'src/locales/*',
64
+ config: 'src/config/*',
65
+ layout: 'src/layout/*',
66
+ },
67
+
68
+ dist: {
69
+ root: 'dist/',
70
+ assets: 'dist/assets/',
71
+ snippets: 'dist/snippets/',
72
+ sections: 'dist/sections/',
73
+ layout: 'dist/layout/',
74
+ templates: 'dist/templates/',
75
+ locales: 'dist/locales/',
76
+ },
77
+
78
+ roots: {
79
+ js: 'src/scripts/*.{js,js.liquid}',
80
+ vendorJs: 'src/scripts/vendor.js',
81
+ css: 'src/styles/*.{css,scss}',
82
+ },
83
+
84
+ plugins: {
85
+ cheerio: {
86
+ run: require('./utilities.js').processSvg,
87
+ },
88
+ postcss: [
89
+ tailwindcss({ config: join(themeRoot, 'tailwind.config.js')}),
90
+ autoprefixer(),
91
+ ]
92
+ },
93
+ };
94
+
95
+ module.exports = config;
@@ -0,0 +1,116 @@
1
+ const chalk = require("chalk");
2
+ const log = require("fancy-log");
3
+
4
+ /**
5
+ * Separates filename and directory from a path string. Returns an object containing both.
6
+ *
7
+ * @param path {String} - a string representing the path to a file
8
+ * @returns {Object} - an object with separated `file` (the filename) and `dir` (path minus filename) properties
9
+ * @private
10
+ */
11
+ function separatePath(path) {
12
+ const tmp = path.split('/');
13
+
14
+ return {
15
+ file: tmp.pop(),
16
+ dir: tmp.join('/'),
17
+ };
18
+ }
19
+
20
+ const messages = {
21
+ logFileEvent: (event, path) => {
22
+ const pathObject = separatePath(path);
23
+
24
+ log('change in',
25
+ chalk.magenta(pathObject.dir),
26
+ chalk.white('-'),
27
+ chalk.cyan(event),
28
+ chalk.yellow(pathObject.file),
29
+ );
30
+ },
31
+
32
+ logTransferDone: () => {
33
+ log('Transfer Complete:',
34
+ chalk.green('File changes successfully synced to store'),
35
+ );
36
+ },
37
+
38
+ logTransferFailed: (errMsg) => {
39
+ log('Transfer Failed:',
40
+ chalk.yellow(`${typeof errMsg === 'string' ? errMsg : 'File(s) failed to upload to store. See log notes in deploy.log'}`),
41
+ );
42
+ },
43
+
44
+ logProcessFiles: (processName) => {
45
+ log('running task',
46
+ chalk.white('-'),
47
+ chalk.cyan(processName),
48
+ );
49
+ },
50
+
51
+ logChildProcess: (cmd) => {
52
+ log('running task',
53
+ chalk.bold('[child process]'),
54
+ chalk.white('-'),
55
+ chalk.cyan('theme', cmd),
56
+ );
57
+ },
58
+
59
+ logDeploys: (cmd, files) => {
60
+ const timestamp = `Deploy complete @ ${new Date()}. `;
61
+ const action = cmd === 'upload' ? 'added/changed ' : 'removed ';
62
+ const amount = `${files.length} file(s): `;
63
+ const fileList = `${files.join(', ')}.\n`;
64
+
65
+ return timestamp + action + amount + fileList;
66
+ },
67
+
68
+ logDeployErrors: (cmd, files, err) => {
69
+ const timestamp = `Deploy error @ ${new Date()}. `;
70
+ const action = cmd === 'upload' ? 'added/changed ' : 'removed ';
71
+ const amount = `${files.length} file(s): `;
72
+ const fileList = `${files.join(', ')}.\n`;
73
+ const errMsg = `${err} \n`;
74
+
75
+ return timestamp + action + amount + fileList + errMsg;
76
+ },
77
+
78
+ logBundleJs: () => {
79
+ log('Updating JS Bundle...');
80
+ },
81
+
82
+ configChange: () => {
83
+ return 'Changes to ThemeKit Config Detected: You may need to quit <slate watch>' +
84
+ ' and run a full <slate deploy> as a result.';
85
+ },
86
+
87
+ translationsFailed: () => {
88
+ return 'Translation errors detected.';
89
+ },
90
+
91
+ invalidThemeId: (themeId, env) => {
92
+ log('Invalid theme id for',
93
+ chalk.cyan(`${env}: ${themeId}`),
94
+ chalk.yellow('`theme_id` must be an integer or "live".'),
95
+ );
96
+ },
97
+
98
+ configError: () => {
99
+ log('File missing:',
100
+ chalk.yellow('`config.yml` does not exist. You need to add a config file before you can make changes to your Shopify store.'),
101
+ );
102
+ },
103
+
104
+ deployTo: (environment) => {
105
+ log('Initiating deploy to', chalk.bold(environment));
106
+ },
107
+
108
+ allDeploysComplete: () => {
109
+ log('Multiple environments:',
110
+ chalk.green('Deploy completed for all environments in series'),
111
+ );
112
+ },
113
+
114
+ };
115
+
116
+ module.exports = messages;