@caweb/cli 1.2.0 → 1.3.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.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/bin/caweb +1 -1
  3. package/bin/wp-cli.phar +0 -0
  4. package/commands/a11y.js +74 -0
  5. package/{lib/commands → commands}/blocks/create-block.js +7 -8
  6. package/{lib/commands → commands}/blocks/update-block.js +3 -9
  7. package/commands/build.js +73 -0
  8. package/{lib/commands → commands/env}/destroy.js +15 -22
  9. package/{lib/commands → commands/env}/start.js +26 -27
  10. package/{lib/commands → commands/env}/stop.js +4 -10
  11. package/{lib/commands → commands}/index.js +51 -43
  12. package/commands/serve.js +78 -0
  13. package/commands/sync.js +498 -0
  14. package/{lib/commands → commands}/tasks/update-plugins.js +2 -2
  15. package/commands/test.js +100 -0
  16. package/configs/aceconfig.js +28 -0
  17. package/{lib/configs.js → configs/docker-compose.js} +30 -83
  18. package/configs/webpack.config.js +119 -0
  19. package/configs/wp-env.js +76 -0
  20. package/gen/parser.js +166 -0
  21. package/gen/site-generator.js +111 -0
  22. package/lib/admin.js +1 -1
  23. package/lib/cli.js +105 -63
  24. package/lib/helpers.js +109 -0
  25. package/lib/index.js +28 -0
  26. package/lib/spinner.js +10 -7
  27. package/lib/{caweb.js → wordpress/caweb.js} +1 -1
  28. package/lib/{divi.js → wordpress/divi.js} +1 -1
  29. package/lib/{download-sources.js → wordpress/download-sources.js} +74 -78
  30. package/lib/wordpress/index.js +16 -0
  31. package/lib/{wordpress.js → wordpress/wordpress.js} +4 -8
  32. package/package.json +41 -27
  33. package/lib/commands/test.js +0 -46
  34. package/lib/utils.js +0 -150
  35. /package/{lib/commands → commands/tasks}/shell.js +0 -0
  36. /package/lib/{options.js → wordpress/options.js} +0 -0
  37. /package/{lib/template → template}/assets/css/popover.css +0 -0
  38. /package/{lib/template → template}/assets/js/popover.js +0 -0
  39. /package/{lib/template → template}/block/edit.js.mustache +0 -0
  40. /package/{lib/template → template}/block/editor.scss.mustache +0 -0
  41. /package/{lib/template → template}/block/index.js.mustache +0 -0
  42. /package/{lib/template → template}/block/save.js.mustache +0 -0
  43. /package/{lib/template → template}/block/style.scss.mustache +0 -0
  44. /package/{lib/template → template}/index.cjs +0 -0
  45. /package/{lib/template → template}/plugin/$slug.php.mustache +0 -0
  46. /package/{lib/template → template}/plugin/core/cdec-api.php.mustache +0 -0
  47. /package/{lib/template → template}/plugin/core/filters.php.mustache +0 -0
  48. /package/{lib/template → template}/plugin/core/functions.php.mustache +0 -0
  49. /package/{lib/template → template}/plugin/inc/renderer.php.mustache +0 -0
@@ -1,78 +1,47 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import path from 'node:path';
5
- import fs from 'fs-extra';
6
- import yaml from 'js-yaml';
4
+ import path from 'path';
5
+ import fs from 'fs';
7
6
  import getHostUser from '@wordpress/env/lib/get-host-user.js';
7
+ import yaml from 'js-yaml';
8
+ import os from 'os';
8
9
 
9
10
  /**
10
- * Promisified dependencies
11
+ * Internal Dependencies
11
12
  */
12
- const { writeFile } = fs.promises;
13
-
14
- const localPath = path.resolve( path.join(process.cwd(), 'node_modules/@caweb/cli/package.json') )
15
- const pkg = JSON.parse( await fs.readFile(localPath) );
16
13
 
17
14
  /**
18
- * Build .wp-env.json
15
+ * Generate config.yml
19
16
  *
20
- * @param {boolean} bare True if excluding any CAWeb Configurations.
21
- * @param {boolean} multisite True if converting to multisite.
22
- * @param {boolean} plugin True if root directory is a plugin.
23
- * @param {boolean} theme True if root directory is a theme.
17
+ * @param {string} workDirectoryPath Path to the work directory located in ~/.wp-env.
24
18
  *
25
- * @returns object
19
+ * @returns void
26
20
  */
27
- const buildWPEnvConfig = (bare, multisite, plugin, theme) => {
28
- let themes = [];
29
- let plugins = [];
30
-
31
- let config = {
32
- core: `WordPress/WordPress#${pkg.config.WP_VER}`,
33
- phpVersion: `${pkg.config.PHP_VER}`,
34
- config: {
35
- ...pkg.config.DEFAULTS
36
- }
37
- }
38
-
39
- // if not bare then include our theme.
40
- if( ! bare ){
41
- themes.push('CAWebPublishing/CAWeb')
42
- }
43
-
44
- // if root directory is a theme
45
- if( theme ){
46
- themes.push( '.' );
47
- }
21
+ async function generateCLIConfig(workDirectoryPath){
22
+ let yml = {
23
+ path: '/var/www/html',
24
+ apache_modules: ['mod_rewrite']
25
+ };
48
26
 
49
- // if is multisite
50
- if( multisite ){
51
- config.config['WP_ALLOW_MULTISITE'] = true;
27
+ let { homedir } = os.userInfo();
28
+
29
+ // add any ssh hosts to the config
30
+ if( fs.existsSync( path.join( homedir, '.ssh', 'config' )) ){
31
+
32
+ let ssh_hosts = fs.readFileSync(path.join( homedir, '.ssh', 'config' )).toString().match(/Host\s+(.*)[^\n\r]/g);
52
33
 
53
- // set CAWeb as Default Theme if it was downloaded
54
- if( ! bare ){
55
- config.config['WP_DEFAULT_THEME'] = 'CAWeb';
56
- }
57
- }
34
+ ssh_hosts.forEach((host) => {
35
+ let s = host.replace(/Host\s+/, '');
58
36
 
59
- // if root directory is a plugin
60
- if( plugin ){
61
- plugins.push( '.' );
62
- }
63
-
64
- // add plugins if sources were added
65
- if( plugins.length ){
66
- config['plugins'] = plugins;
67
- }
37
+ yml[`@${s}`] = { ssh: s};
38
+ })
39
+ }
68
40
 
69
- // add themes if sources were added
70
- if( themes.length ){
71
- config['themes'] = themes;
72
- }
73
41
 
74
- return config;
75
-
42
+ fs.writeFileSync(
43
+ path.join(workDirectoryPath, 'config.yml'),
44
+ yaml.dump(yml));
76
45
  }
77
46
 
78
47
  /**
@@ -81,8 +50,8 @@ const buildWPEnvConfig = (bare, multisite, plugin, theme) => {
81
50
  * @param {string} workDirectoryPath Path to the work directory located in ~/.wp-env.
82
51
  * @returns object
83
52
  */
84
- const buildDockerComposeConfig = (workDirectoryPath) => {
85
- const {name} = getHostUser();
53
+ export default function dockerConfig ( workDirectoryPath ) {
54
+ const {name} = getHostUser();
86
55
 
87
56
  // generate cli config file for cli containers.
88
57
  generateCLIConfig(workDirectoryPath);
@@ -175,27 +144,5 @@ const buildDockerComposeConfig = (workDirectoryPath) => {
175
144
  }
176
145
 
177
146
  return dockerConfig;
178
- }
179
-
180
- /**
181
- * Generate config.yml
182
- *
183
- * @param {string} workDirectoryPath Path to the work directory located in ~/.wp-env.
184
- *
185
- * @returns void
186
- */
187
- async function generateCLIConfig(workDirectoryPath){
188
- const yml = {
189
- path: '/var/www/html',
190
- apache_modules: ['mod_rewrite']
191
- };
192
-
193
- await writeFile(
194
- path.join(workDirectoryPath, 'config.yml'),
195
- yaml.dump(yml));
196
- }
197
-
198
- export {
199
- buildWPEnvConfig,
200
- buildDockerComposeConfig
147
+
201
148
  }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * WebPack Configuration for California Department of Technology
3
+ *
4
+ * Utilizes WordPress Scripts Webpack configuration as base.
5
+ * s
6
+ * @link https://webpack.js.org/configuration/
7
+ */
8
+
9
+ /**
10
+ * External dependencies
11
+ */
12
+ import baseConfig from '@wordpress/scripts/config/webpack.config.js';
13
+ import path from 'path';
14
+ import fs from 'fs';
15
+ import MiniCssExtractPlugin from "mini-css-extract-plugin";
16
+ import CopyWebpackPlugin from 'copy-webpack-plugin';
17
+
18
+ /**
19
+ * Internal dependencies
20
+ */
21
+ import SiteGenerator from '../gen/site-generator.js';
22
+
23
+ // fallback to env variable
24
+ let isProduction = "production" === process.env.NODE_ENV;
25
+
26
+ // because we use WordPress default WebPack config
27
+ // 'mode' is defined by process.env.NODE_ENV
28
+ // some of the webpack cli flags are ignored
29
+ // so let's make some corrections.
30
+ let corrections = {};
31
+
32
+ process.argv.splice( 2 ).forEach(element => {
33
+ // if flag
34
+ if( element.startsWith( '--' ) ){
35
+ let splitterIndex = element.indexOf( '=' );
36
+ let flag = element.substring(2, splitterIndex );
37
+ let value = element.substring( splitterIndex + 1 );
38
+
39
+ // if flag is a webpack flag add corrections.
40
+ switch( flag ){
41
+ case 'mode':
42
+ // if cli arg was passed use that value
43
+ isProduction = "production" === value;
44
+
45
+ corrections[flag] = value
46
+ break
47
+ }
48
+
49
+ }
50
+
51
+ });
52
+
53
+
54
+ // update the WordPress default webpack rules with ours.
55
+ baseConfig.module.rules.forEach((rule, i) => {
56
+ const r = new RegExp(rule.test).toString();
57
+
58
+ // WordPress adds a hash to asset file names we remove that hash
59
+ if( r === new RegExp(/\.(bmp|png|jpe?g|gif|webp)$/i).toString() ){
60
+ baseConfig.module.rules[i].generator = {
61
+ filename: 'images/[name][ext]'
62
+ }
63
+ }
64
+ if( r === new RegExp(/\.(woff|woff2|eot|ttf|otf)$/i).toString() ){
65
+ baseConfig.module.rules[i].generator = {
66
+ filename: 'fonts/[name][ext]'
67
+ }
68
+ }
69
+ // SVG rules
70
+ if( r === new RegExp(/\.svg$/).toString() ){
71
+ // we don't want SVG to be inline move them to fonts folder
72
+ if( 'asset/inline' === rule.type ){
73
+ baseConfig.module.rules[i].type = 'asset/resource';
74
+ baseConfig.module.rules[i].generator = {
75
+ filename: 'fonts/[name][ext]'
76
+ };
77
+ }
78
+ }
79
+ })
80
+
81
+ // Our Webpack Configuration.
82
+ let webpackConfig = {
83
+ ...baseConfig,
84
+ target: 'browserslist',
85
+ devtool: false,
86
+ output: {
87
+ ...baseConfig.output,
88
+ publicPath: `/`,
89
+ clean: false
90
+ },
91
+ plugins: [
92
+ ...baseConfig.plugins,
93
+ new MiniCssExtractPlugin(
94
+ {
95
+ linkType: "text/css",
96
+ filename: '[name].css'
97
+ }
98
+ )
99
+ ],
100
+ module: {
101
+ rules: [
102
+ ...baseConfig.module.rules,
103
+ {
104
+ test: /\.html$/,
105
+ loader: 'handlebars-loader'
106
+ }
107
+ ]
108
+ },
109
+ performance: {
110
+ maxAssetSize: 500000,
111
+ maxEntrypointSize: 500000
112
+ }
113
+ };
114
+
115
+ if( ! isProduction ){
116
+ SiteGenerator( webpackConfig );
117
+ }
118
+
119
+ export default webpackConfig;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import path from 'path';
5
+ import fs from 'fs';
6
+
7
+ /**
8
+ * Internal Dependencies
9
+ */
10
+ import {
11
+ projectPath
12
+ } from '../lib/helpers.js';
13
+
14
+ const localFile = path.join(projectPath, 'package.json');
15
+ const pkg = JSON.parse( fs.readFileSync(localFile) );
16
+
17
+ /**
18
+ * Build .wp-env.json
19
+ *
20
+ * @param {boolean} bare True if excluding any CAWeb Configurations.
21
+ * @param {boolean} multisite True if converting to multisite.
22
+ * @param {boolean} plugin True if root directory is a plugin.
23
+ * @param {boolean} theme True if root directory is a theme.
24
+ *
25
+ * @returns object
26
+ */
27
+ export default function wpEnvConfig ( bare, multisite, plugin, theme ) {
28
+ let themes = [];
29
+ let plugins = [];
30
+
31
+ let config = {
32
+ core: `WordPress/WordPress#${pkg.config.WP_VER}`,
33
+ phpVersion: `${pkg.config.PHP_VER}`,
34
+ config: {
35
+ ...pkg.config.DEFAULTS
36
+ }
37
+ }
38
+
39
+ // if not bare then include our theme.
40
+ if( ! bare ){
41
+ themes.push('CAWebPublishing/CAWeb')
42
+ }
43
+
44
+ // if root directory is a theme
45
+ if( theme ){
46
+ themes.push( '.' );
47
+ }
48
+
49
+ // if is multisite
50
+ if( multisite ){
51
+ config.config['WP_ALLOW_MULTISITE'] = true;
52
+
53
+ // set CAWeb as Default Theme if it was downloaded
54
+ if( ! bare ){
55
+ config.config['WP_DEFAULT_THEME'] = 'CAWeb';
56
+ }
57
+ }
58
+
59
+ // if root directory is a plugin
60
+ if( plugin ){
61
+ plugins.push( '.' );
62
+ }
63
+
64
+ // add plugins if sources were added
65
+ if( plugins.length ){
66
+ config['plugins'] = plugins;
67
+ }
68
+
69
+ // add themes if sources were added
70
+ if( themes.length ){
71
+ config['themes'] = themes;
72
+ }
73
+
74
+ return config;
75
+
76
+ }
package/gen/parser.js ADDED
@@ -0,0 +1,166 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { HTMLToJSON } from 'html-to-json-parser';
7
+ import jsdom from 'jsdom';
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+
13
+ /**
14
+ * Path Directory Locations
15
+ * - appPath - Project Application Path
16
+ * - srcPath - Project Application Src Path
17
+ * - publicPath - Project Application Public Path
18
+ * - dataPath - Project Application Data Path
19
+ */
20
+ const appPath = path.resolve(process.cwd());
21
+ const srcPath = path.join( appPath, 'src');
22
+ const dataPath = path.join( srcPath, 'data');
23
+ const assetsPath = path.join( srcPath, 'assets');
24
+
25
+ const fallbackPath = path.join( appPath, 'node_modules', '@cdt', 'template');
26
+
27
+ /**
28
+ * Generate Pages
29
+ *
30
+ * @async
31
+ * @param {Object} siteData Data to use when creating pages
32
+ * @returns {string}
33
+ */
34
+ async function generatePages(siteData){
35
+
36
+ // we start with a blank html and schema
37
+ let page = '<html><html>';
38
+ let schema = {};
39
+
40
+ // if src/index.html exists
41
+ if(fs.existsSync(path.join(srcPath, 'index.html'))){
42
+
43
+ // get index path file location
44
+ page = path.join(srcPath, 'index.html')
45
+
46
+ // generate page schema
47
+ schema = await convertHTMLtoJson(page, false);
48
+
49
+ // read contents of index file, we strip any newlines
50
+ //page = fs.readFileSync( page ).toString().replace(/\n[\s]+/g,'');
51
+ }
52
+
53
+ // convert page to jsdom object
54
+ let dom = new jsdom.JSDOM( page );
55
+
56
+ // if we should be using the template
57
+ if( process.env.CDT_TEMPLATE ){
58
+
59
+ // read contents of template index file, we strip any newlines
60
+ page = fs.readFileSync( path.join(fallbackPath, 'src', 'index.html') ).toString().replace(/\n[\s]+/g,'');
61
+
62
+ // create template jsdom object
63
+ let templateDom = new jsdom.JSDOM( page );
64
+
65
+ // colorscheme
66
+ let colorCSS = path.join(fallbackPath, 'build', 'oceanside.css');
67
+ let colorJS = path.join(fallbackPath, 'build', 'oceanside.js');
68
+
69
+ dom.window.document.querySelector('head').append(
70
+ `<link rel="stylesheet" type="text/css" href="${colorCSS}">`
71
+ );
72
+
73
+
74
+ // update template dom by appending contents of existing dom body
75
+ // after the header
76
+ templateDom.window.document.querySelector('header').append(
77
+ dom.window.document.querySelector('body')
78
+ );
79
+
80
+ // update existing dom with templated changes.
81
+ dom = new jsdom.JSDOM( templateDom.window.document.documentElement.outerHTML);
82
+ }
83
+
84
+ // generate any data attributes
85
+ populateDataAttrs( dom, siteData, schema );
86
+
87
+ return dom.window.document.documentElement.outerHTML;
88
+
89
+ }
90
+
91
+
92
+ /**
93
+ * Populate data-cagov attributes with siteData
94
+ *
95
+ * @param {jsdom.JSDOM} dom HTML
96
+ * @param {Object} siteData
97
+ * @param {Object} schema
98
+ */
99
+ function populateDataAttrs(dom, siteData, schema){
100
+ for( const [attr, data] of Object.entries(siteData) ){
101
+ // if attribute isn't in the schema don't do anything
102
+ if( ! schema.data || ! Object.keys(schema.data).includes(attr) ){
103
+ continue;
104
+ }
105
+
106
+ // any data- attributes should be prefixed with cagov
107
+ // get any elements with the appropriate data- attr
108
+ let elements = dom.window.document.querySelectorAll(`[data-cagov-${attr}]`);
109
+
110
+ // if the data is an array|object pass as data
111
+ let value = Array.isArray(data) || 'object' === typeof data ? JSON.stringify( data ) : data;
112
+
113
+ elements.forEach(element => {
114
+ element.setAttribute(`data-cagov-${attr}`, value);
115
+ });
116
+
117
+ }
118
+ }
119
+
120
+
121
+ /**
122
+ * Generates a page schema including any data attributes in src/data/index.json
123
+ *
124
+ * @async
125
+ * @param {*} file
126
+ * @param {boolean} [write=true]
127
+ * @param {string} [outputPath='']
128
+ * @returns {unknown}
129
+ */
130
+ async function convertHTMLtoJson( file, write = true, outputPath = '' ){
131
+ if( fs.existsSync( file )){
132
+ let template = fs.readFileSync( file ).toString().replace(/\n[\s]+/g,'');
133
+ let markup = await HTMLToJSON(template, false )
134
+
135
+ let data = fs.existsSync( path.join(dataPath, 'index.json') ) ?
136
+ JSON.parse( fs.readFileSync( path.join(dataPath, 'index.json') ) ) : {};
137
+
138
+ // remove any examples data
139
+ delete data.examples;
140
+
141
+ let schema = {
142
+ title: "California Department of Technology Schema",
143
+ $schema: "http://json-schema.org/2019-09/schema",
144
+ $id: "https://json-schema.org/draft/2019-09/schema",
145
+ type: "object",
146
+ description: "California Department of Technology Schema",
147
+ data,
148
+ markup,
149
+ };
150
+
151
+ // Write schema file.
152
+ if( write ){
153
+ fs.writeFileSync(
154
+ path.join(outputPath, 'schema.json'),
155
+ JSON.stringify( schema, null, 4 )
156
+ );
157
+ }else{
158
+ return schema;
159
+ }
160
+
161
+ }
162
+ }
163
+
164
+ export {
165
+ generatePages
166
+ };
@@ -0,0 +1,111 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import path from 'path';
5
+ import fs from 'fs';
6
+ import HtmlWebpackPlugin from 'html-webpack-plugin';
7
+ import jsdom from 'jsdom';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import {
14
+ generatePages
15
+ } from './parser.js';
16
+
17
+ import {
18
+ projectPath,
19
+ appPath
20
+ } from '../lib/helpers.js';
21
+
22
+ const srcPath = path.join( appPath, 'src');
23
+ const dataPath = path.join( srcPath, 'data');
24
+ const assetsPath = path.join( srcPath, 'assets');
25
+
26
+ // default meta used for site generation when no meta is passed
27
+ const meta = {
28
+ "Author": "CAWebPublishing",
29
+ "Description": "State of California",
30
+ "Keywords": "California,government",
31
+ "viewport": "width=device-width, initial-scale=1.0, minimum-scale=1.0"
32
+ }
33
+
34
+
35
+ /**
36
+ * Returns an object containing all data from site.json and src/data/examples.json
37
+ *
38
+ * @returns {Object}
39
+ */
40
+ function getSiteData(){
41
+
42
+ // grab any sample data if it exists.
43
+ let sample = fs.existsSync( path.join(dataPath, 'examples.json') ) ? JSON.parse( fs.readFileSync( path.join(dataPath, 'examples.json') ) ) : {};
44
+
45
+ // grab any site data if it exists.
46
+ let site = fs.existsSync( path.join(appPath, 'site.json') ) ? JSON.parse( fs.readFileSync( path.join(appPath, 'site.json') ) ) : {};
47
+
48
+ // merge datasets together
49
+ let siteData = {
50
+ ...sample,
51
+ ...site
52
+ };
53
+
54
+ return siteData;
55
+ }
56
+
57
+ export default (webpackConfig) => {
58
+ // we only proceed if and index.html exists
59
+ if( ! fs.existsSync( path.join( srcPath, 'index.html' )) ){
60
+ return;
61
+ }
62
+
63
+ // we only want to display errors and warnings
64
+ webpackConfig.stats = 'errors-warnings';
65
+
66
+ // get site data
67
+ let siteData = getSiteData();
68
+
69
+ // if favicon doesn't exist use fallback asset.
70
+ let favicon = fs.existsSync(path.join(assetsPath, 'images', 'favicon.ico')) ?
71
+ path.join(assetsPath, 'images', 'favicon.ico') :
72
+ path.join(projectPath, 'assets', 'favicon.ico') ;
73
+
74
+ let defaultPage = {
75
+ minify: false,
76
+ favicon,
77
+ meta: siteData.meta || meta,
78
+ }
79
+
80
+ // add html
81
+ webpackConfig.plugins = [
82
+ ...webpackConfig.plugins,
83
+ new HtmlWebpackPlugin({
84
+ filename: path.join( process.cwd(), 'public', 'index.html'),
85
+ template: path.join(srcPath, 'index.html'),
86
+ //templateContent: generatePages(siteData),
87
+ title: 'Test Site',
88
+ ...defaultPage
89
+ })
90
+ ]
91
+
92
+ // add devServer
93
+ webpackConfig.devServer = {
94
+ devMiddleware: {
95
+ writeToDisk: true,
96
+ },
97
+ hot: false,
98
+ allowedHosts: 'auto',
99
+ host: 'localhost',
100
+ port: 9000,
101
+ compress: true,
102
+ proxy: {
103
+ '/public': {
104
+ pathRewrite: {
105
+ '^/build': '',
106
+ },
107
+ },
108
+ },
109
+ }
110
+
111
+ };
package/lib/admin.js CHANGED
@@ -32,7 +32,7 @@ export default async function generateOverridesMD() {
32
32
  }
33
33
  }
34
34
 
35
- await fs.writeFileSync(
35
+ fs.writeFileSync(
36
36
  path.join(process.cwd(), 'docs', 'OVERRIDES.MD'),
37
37
  output.join('\n')
38
38
  );