@lipemat/js-boilerplate 8.4.0 → 8.6.0-beta.2
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.
- package/README.md +1 -2
- package/config/css-loader.config.js +44 -0
- package/config/jest.config.js +3 -0
- package/config/postcss.config.js +1 -1
- package/config/webpack.dev.js +7 -17
- package/config/webpack.dist.js +10 -17
- package/helpers/css-classnames.js +106 -0
- package/helpers/package-config.js +6 -8
- package/package.json +11 -8
package/README.md
CHANGED
|
@@ -21,7 +21,6 @@ Add the following to your package.json. (this may also be found in the `template
|
|
|
21
21
|
```json
|
|
22
22
|
{
|
|
23
23
|
"jsPath": "./js",
|
|
24
|
-
"themeUrlPath": "/wp-content/themes/core/",
|
|
25
24
|
"scripts": {
|
|
26
25
|
"browserslist": "lipemat-js-boilerplate browserslist",
|
|
27
26
|
"dist": "lipemat-js-boilerplate dist",
|
|
@@ -39,8 +38,8 @@ Add the following to your package.json. (this may also be found in the `template
|
|
|
39
38
|
```
|
|
40
39
|
**_You may adjust things as needed but be sure to leave the `scripts` as is._**
|
|
41
40
|
|
|
41
|
+
* `shortCssClasses`: Enable short 1-2 character CSS classes. Recommended if you're not running multiple instances of this package on the same site.
|
|
42
42
|
* `jsPath`: Path of JS application relative to `package.json`. If `package.json` is in same directory as the JS application, this may be omitted.
|
|
43
|
-
* `themeUrlPath`: Path of `package.json` file relative to site's domain.
|
|
44
43
|
|
|
45
44
|
## Code Completion In PHPStorm
|
|
46
45
|
Some `@types` have been specified in this library to assist with code completion and allow using the built-in TypeScript support. Unfortunately, some typescripts still send errors to PHPStorm like "Default export is not declared in an imported module". I've found that it's easier to just remove this warning by un-checking `Editor -> Inspections -> JavaScript -> General -> Validate Imports`. (this may not need to be un-checked if you enable the built-in TypeScript support).
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const config = require( '../helpers/package-config' );
|
|
2
|
+
const {getLocalIdent} = require( '../helpers/css-classnames' );
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Options for the Webpack `css-loader`.
|
|
6
|
+
*
|
|
7
|
+
* Extracted to its on file to allow easy overrides.
|
|
8
|
+
*
|
|
9
|
+
* @since 8.6.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
let cssLoader = {
|
|
13
|
+
importLoaders: 1,
|
|
14
|
+
modules: {
|
|
15
|
+
exportLocalsConvention: 'camelCase',
|
|
16
|
+
localIdentName: 'Ⓜ[name]__[local]__[contenthash:base64:2]',
|
|
17
|
+
// Default to :global for classes in "global" directories.
|
|
18
|
+
mode: resourcePath => {
|
|
19
|
+
return /globals?\//i.test( resourcePath.replace( /\\/g, '/' ) ) ? 'global' : 'local';
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
sourceMap: true,
|
|
23
|
+
url: false,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
if ( 'production' === process.env.NODE_ENV ) {
|
|
27
|
+
cssLoader = {
|
|
28
|
+
importLoaders: 1,
|
|
29
|
+
modules: {
|
|
30
|
+
exportLocalsConvention: 'camelCase',
|
|
31
|
+
// Use short CSS Classes if enabled.
|
|
32
|
+
...config.shortCssClasses ? {getLocalIdent} : {},
|
|
33
|
+
// Hash used when short CSS classes are not enabled.
|
|
34
|
+
localIdentName: '[contenthash:base64:5]',
|
|
35
|
+
// Default to :global for classes in "global" directories.
|
|
36
|
+
mode: resourcePath => {
|
|
37
|
+
return /globals?\//i.test( resourcePath.replace( /\\/g, '/' ) ) ? 'global' : 'local';
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
url: false,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = cssLoader;
|
package/config/jest.config.js
CHANGED
package/config/postcss.config.js
CHANGED
package/config/webpack.dev.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
const {getConfig, hasLocalOverride} = require( '../helpers/config' );
|
|
1
2
|
const webpack = require( 'webpack' );
|
|
2
3
|
const path = require( 'path' );
|
|
3
4
|
const fs = require( 'fs' );
|
|
4
|
-
const configHelper = require( '../helpers/config' );
|
|
5
5
|
const ForkTsCheckerWebpackPlugin = require( 'fork-ts-checker-webpack-plugin' );
|
|
6
6
|
const config = require( '../helpers/package-config' );
|
|
7
|
-
|
|
8
|
-
const
|
|
7
|
+
|
|
8
|
+
const postCSSOptions = getConfig( 'postcss.config.js' );
|
|
9
|
+
const babelOptions = getConfig( 'babel.config.js' );
|
|
10
|
+
const cssLoaderOptions = getConfig( 'css-loader.config.js' );
|
|
9
11
|
|
|
10
12
|
// To allow line numbers to show up in console errors. @see React Error Boundaries.
|
|
11
13
|
babelOptions.plugins.unshift( '@babel/plugin-transform-react-jsx-source' );
|
|
@@ -19,7 +21,7 @@ const plugins = [
|
|
|
19
21
|
|
|
20
22
|
// Loads a thread, which verifies any TypeScripts on changes.
|
|
21
23
|
// Only use this if the project has a tsconfig.json file.
|
|
22
|
-
if (
|
|
24
|
+
if ( hasLocalOverride( 'tsconfig.json', true ) ) {
|
|
23
25
|
plugins.push( new ForkTsCheckerWebpackPlugin( {
|
|
24
26
|
formatter: 'basic',
|
|
25
27
|
logger: {
|
|
@@ -92,19 +94,7 @@ module.exports = {
|
|
|
92
94
|
'style-loader',
|
|
93
95
|
{
|
|
94
96
|
loader: 'css-loader',
|
|
95
|
-
options:
|
|
96
|
-
importLoaders: 1,
|
|
97
|
-
modules: {
|
|
98
|
-
exportLocalsConvention: 'camelCase',
|
|
99
|
-
localIdentName: 'Ⓜ[name]__[local]__[contenthash:base64:2]',
|
|
100
|
-
// Default to :global for classes in "global" directories.
|
|
101
|
-
mode: resourcePath => {
|
|
102
|
-
return /globals?\//i.test( resourcePath.replace( /\\/g, '/' ) ) ? 'global' : 'local';
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
sourceMap: true,
|
|
106
|
-
url: false,
|
|
107
|
-
},
|
|
97
|
+
options: cssLoaderOptions,
|
|
108
98
|
},
|
|
109
99
|
{
|
|
110
100
|
loader: '@lipemat/postcss-loader',
|
package/config/webpack.dist.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
const {getConfig} = require( '../helpers/config' );
|
|
1
2
|
const moduleHelpers = require( '../helpers/modules' );
|
|
2
3
|
const webpack = require( 'webpack' );
|
|
3
4
|
const path = require( 'path' );
|
|
4
5
|
const fs = require( 'fs' );
|
|
5
6
|
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
|
|
6
7
|
const WebpackCleanupPlugin = require( '@lipemat/webpack-cleanup-plugin' );
|
|
7
|
-
const config = require( '../helpers/package-config' );
|
|
8
|
-
const postCSSOptions = require( '../helpers/config' ).getConfig( 'postcss.config.js' );
|
|
9
|
-
const babelOptions = require( '../helpers/config' ).getConfig( 'babel.config.js' );
|
|
10
8
|
const WebpackAssetsManifest = require( 'webpack-assets-manifest' );
|
|
11
9
|
const SriPlugin = require( 'webpack-subresource-integrity' );
|
|
10
|
+
const config = require( '../helpers/package-config' );
|
|
11
|
+
|
|
12
|
+
const postCSSOptions = getConfig( 'postcss.config.js' );
|
|
13
|
+
const babelOptions = getConfig( 'babel.config.js' );
|
|
14
|
+
const cssLoaderOptions = getConfig( 'css-loader.config.js' );
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
const entry = {
|
|
14
18
|
master: [
|
|
@@ -55,7 +59,7 @@ module.exports = {
|
|
|
55
59
|
output: {
|
|
56
60
|
path: path.resolve( config.workingDirectory, 'dist' ),
|
|
57
61
|
filename: '[name].js',
|
|
58
|
-
publicPath:
|
|
62
|
+
publicPath: 'auto', // Change this if you want to use an external CDN etc.
|
|
59
63
|
chunkFilename: '[name].[chunkhash].js',
|
|
60
64
|
crossOriginLoading: 'anonymous',
|
|
61
65
|
},
|
|
@@ -72,7 +76,7 @@ module.exports = {
|
|
|
72
76
|
$: 'jquery',
|
|
73
77
|
} ),
|
|
74
78
|
new MiniCssExtractPlugin( {
|
|
75
|
-
filename: '
|
|
79
|
+
filename: '[name].css',
|
|
76
80
|
chunkFilename: '[name].[chunkhash].css',
|
|
77
81
|
} ),
|
|
78
82
|
new WebpackCleanupPlugin(),
|
|
@@ -98,18 +102,7 @@ module.exports = {
|
|
|
98
102
|
MiniCssExtractPlugin.loader,
|
|
99
103
|
{
|
|
100
104
|
loader: 'css-loader',
|
|
101
|
-
options:
|
|
102
|
-
importLoaders: 1,
|
|
103
|
-
modules: {
|
|
104
|
-
exportLocalsConvention: 'camelCase',
|
|
105
|
-
localIdentName: '[contenthash:base64:5]',
|
|
106
|
-
// Default to :global for classes in "global" directories.
|
|
107
|
-
mode: resourcePath => {
|
|
108
|
-
return /globals?\//i.test( resourcePath.replace( /\\/g, '/' ) ) ? 'global' : 'local';
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
url: false,
|
|
112
|
-
},
|
|
105
|
+
options: cssLoaderOptions,
|
|
113
106
|
},
|
|
114
107
|
{
|
|
115
108
|
loader: '@lipemat/postcss-loader',
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const SHORT_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
2
|
+
const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
3
|
+
|
|
4
|
+
const classes = {};
|
|
5
|
+
let counters = [ -1 ];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Reset all counters.
|
|
9
|
+
*
|
|
10
|
+
* @notice Mostly here for unit tests.
|
|
11
|
+
*/
|
|
12
|
+
function resetCounters() {
|
|
13
|
+
counters = [ -1 ];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get the next class is sequence based on:
|
|
18
|
+
* 1. Single character from SHORT_ALPHABET (prevent conflicts with CSS boilerplate).
|
|
19
|
+
* 2. Incremented character from the `ALPHABET`.
|
|
20
|
+
* 1. Used once require 2+ characters.
|
|
21
|
+
* 2. Grows to 3+ characters as needed.
|
|
22
|
+
*
|
|
23
|
+
* @return {string}
|
|
24
|
+
*/
|
|
25
|
+
function getNextClass() {
|
|
26
|
+
const last = counters.length - 1;
|
|
27
|
+
let totalLetters = ALPHABET.length - 1;
|
|
28
|
+
|
|
29
|
+
// First level uses the SHORT_ALPHABET.
|
|
30
|
+
if ( 0 === last ) {
|
|
31
|
+
totalLetters = SHORT_ALPHABET.length - 1;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if ( counters[ last ] < totalLetters ) {
|
|
35
|
+
counters[ last ]++;
|
|
36
|
+
} else {
|
|
37
|
+
incrementParent();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return counters.map( ( counter, i ) => {
|
|
41
|
+
return 0 === i ? SHORT_ALPHABET[ counter ] : ALPHABET[ counter ];
|
|
42
|
+
} ).join( '' );
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* When we run out of characters on the current level:
|
|
48
|
+
* 1. Increment the parent level.
|
|
49
|
+
* 2. Reset current level and all child levels back to 0.
|
|
50
|
+
*
|
|
51
|
+
* If we are out of characters on the parent level or have
|
|
52
|
+
* no parent level:
|
|
53
|
+
* 1. Add a new child level.
|
|
54
|
+
* 2. Reset all levels back to 0.
|
|
55
|
+
*
|
|
56
|
+
*/
|
|
57
|
+
function incrementParent() {
|
|
58
|
+
let parent = counters.length - 2;
|
|
59
|
+
let totalLetters = ALPHABET.length - 1;
|
|
60
|
+
|
|
61
|
+
while ( counters[ parent ] !== undefined ) {
|
|
62
|
+
// First level uses the SHORT_ALPHABET.
|
|
63
|
+
if ( 0 === parent ) {
|
|
64
|
+
totalLetters = SHORT_ALPHABET.length - 1;
|
|
65
|
+
}
|
|
66
|
+
if ( counters[ parent ] < totalLetters ) {
|
|
67
|
+
counters[ parent ]++;
|
|
68
|
+
// Reset all child levels to 0.
|
|
69
|
+
while ( counters[ parent + 1 ] !== undefined ) {
|
|
70
|
+
counters[ parent + 1 ] = 0;
|
|
71
|
+
parent++;
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
parent--;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Add a new level and reset all existing levels.
|
|
79
|
+
counters.forEach( ( _, i ) => counters[ i ] = 0 );
|
|
80
|
+
counters.push( 0 );
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Return a single character unique CSS class name based on WebPack
|
|
85
|
+
* css-loader's `getLocalIdentName` callback.
|
|
86
|
+
*
|
|
87
|
+
* Tracks CSS classes per each file so duplicate uses of the
|
|
88
|
+
* same class in a file receive the same result.
|
|
89
|
+
*
|
|
90
|
+
* @notice Only enabled if the `package.json` has `shortCssClasses` set to true.
|
|
91
|
+
*
|
|
92
|
+
* @link https://webpack.js.org/loaders/css-loader/#getlocalident
|
|
93
|
+
*/
|
|
94
|
+
const getLocalIdent = ( {resourcePath}, _, localName ) => {
|
|
95
|
+
classes[ resourcePath ] ||= {};
|
|
96
|
+
classes[ resourcePath ][ localName ] ||= getNextClass();
|
|
97
|
+
return classes[ resourcePath ][ localName ];
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
module.exports = {
|
|
101
|
+
ALPHABET,
|
|
102
|
+
SHORT_ALPHABET,
|
|
103
|
+
getLocalIdent,
|
|
104
|
+
getNextClass,
|
|
105
|
+
resetCounters,
|
|
106
|
+
};
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get all configurations for package.json of the project running this.
|
|
3
|
-
*/
|
|
4
1
|
const path = require( 'path' );
|
|
5
2
|
const fs = require( 'fs' );
|
|
6
|
-
const workingDirectory = fs.realpathSync( process.cwd() );
|
|
7
3
|
|
|
4
|
+
const workingDirectory = fs.realpathSync( process.cwd() );
|
|
8
5
|
let packageConfig = require( path.resolve( workingDirectory, 'package.json' ) );
|
|
9
|
-
packageConfig.es6Modules
|
|
6
|
+
packageConfig.es6Modules ||= [];
|
|
7
|
+
packageConfig.jsPath ||= '';
|
|
10
8
|
// Path of the package.json file (root).
|
|
11
9
|
packageConfig.packageDirectory = workingDirectory;
|
|
12
|
-
packageConfig.
|
|
13
|
-
packageConfig.url = packageConfig.url || 'http://localhost';
|
|
10
|
+
packageConfig.url ||= 'http://localhost';
|
|
14
11
|
// Path of JS application files.
|
|
15
|
-
packageConfig.workingDirectory = packageConfig.jsPath ? path.resolve( packageConfig.jsPath ) : workingDirectory;
|
|
12
|
+
packageConfig.workingDirectory = packageConfig.jsPath !== '' ? path.resolve( packageConfig.jsPath ) : workingDirectory;
|
|
13
|
+
packageConfig.shortCssClasses ||= false;
|
|
16
14
|
|
|
17
15
|
try {
|
|
18
16
|
const localConfig = require( path.resolve( workingDirectory, './local-config.json' ) );
|
package/package.json
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lipemat/js-boilerplate",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.6.0-beta.2",
|
|
4
4
|
"description": "Dependencies and scripts for a no config JavaScript app",
|
|
5
|
+
"author": "Mat Lipe",
|
|
6
|
+
"license": "MIT",
|
|
5
7
|
"engines": {
|
|
6
8
|
"node": ">=14.17.6"
|
|
7
9
|
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/lipemat/js-boilerplate/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/lipemat/js-boilerplate#readme",
|
|
8
14
|
"repository": {
|
|
9
15
|
"type": "git",
|
|
10
16
|
"url": "git+https://github.com/lipemat/js-boilerplate.git"
|
|
11
17
|
},
|
|
18
|
+
"sideEffects": false,
|
|
12
19
|
"keywords": [
|
|
13
20
|
"react",
|
|
14
21
|
"boilerplate",
|
|
@@ -25,9 +32,9 @@
|
|
|
25
32
|
"bin": {
|
|
26
33
|
"lipemat-js-boilerplate": "bin/lipemat-js-boilerplate.js"
|
|
27
34
|
},
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test": "lipemat-js-boilerplate test --silent"
|
|
37
|
+
},
|
|
31
38
|
"dependencies": {
|
|
32
39
|
"@babel/core": "^7.4.3",
|
|
33
40
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
|
@@ -81,9 +88,5 @@
|
|
|
81
88
|
"webpack-dev-server": "^4.7.2",
|
|
82
89
|
"webpack-subresource-integrity": "^1.5.2"
|
|
83
90
|
},
|
|
84
|
-
"bugs": {
|
|
85
|
-
"url": "https://github.com/lipemat/js-boilerplate/issues"
|
|
86
|
-
},
|
|
87
|
-
"homepage": "https://github.com/lipemat/js-boilerplate#readme",
|
|
88
91
|
"packageManager": "yarn@3.2.0"
|
|
89
92
|
}
|