@lipemat/js-boilerplate 8.4.0 → 8.5.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.
@@ -14,6 +14,9 @@ let jestConfig = {
14
14
  moduleNameMapper: {
15
15
  '\\.(pcss|less|css)$': 'identity-obj-proxy',
16
16
  },
17
+ roots: [
18
+ './tests',
19
+ ],
17
20
  testURL: packageConfig.url,
18
21
  transform: {
19
22
  '^.+\\.[tj]sx?$': [ 'babel-jest', babelConfig ],
@@ -1,4 +1,5 @@
1
1
  const moduleHelpers = require( '../helpers/modules' );
2
+ const {getLocalIdent} = require( '../helpers/css-classnames' );
2
3
  const webpack = require( 'webpack' );
3
4
  const path = require( 'path' );
4
5
  const fs = require( 'fs' );
@@ -102,6 +103,9 @@ module.exports = {
102
103
  importLoaders: 1,
103
104
  modules: {
104
105
  exportLocalsConvention: 'camelCase',
106
+ // Use short CSS Classes if enabled.
107
+ ...config.shortCssClasses ? {getLocalIdent} : {},
108
+ // Hash used when short CSS classes are not enabled.
105
109
  localIdentName: '[contenthash:base64:5]',
106
110
  // Default to :global for classes in "global" directories.
107
111
  mode: resourcePath => {
@@ -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 shortAlphabet (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
+ };
package/package.json CHANGED
@@ -1,14 +1,21 @@
1
1
  {
2
2
  "name": "@lipemat/js-boilerplate",
3
- "version": "8.4.0",
3
+ "version": "8.5.0",
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
- "author": "Mat Lipe",
29
- "license": "MIT",
30
- "sideEffects": false,
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
  }