@lipemat/js-boilerplate-shared 0.0.1
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 -0
- package/config/jest.config.js +29 -0
- package/config/jest.config.js.map +1 -0
- package/config/jest.config.ts +31 -0
- package/helpers/browserslist.js +18 -0
- package/helpers/browserslist.js.map +1 -0
- package/helpers/browserslist.ts +18 -0
- package/helpers/camel-case.js +93 -0
- package/helpers/camel-case.js.map +1 -0
- package/helpers/camel-case.ts +101 -0
- package/helpers/config.js +61 -0
- package/helpers/config.js.map +1 -0
- package/helpers/config.ts +66 -0
- package/helpers/css-classnames.js +104 -0
- package/helpers/css-classnames.js.map +1 -0
- package/helpers/css-classnames.ts +124 -0
- package/helpers/package-config.js +45 -0
- package/helpers/package-config.js.map +1 -0
- package/helpers/package-config.ts +97 -0
- package/helpers/postcss-config.js +135 -0
- package/helpers/postcss-config.js.map +1 -0
- package/helpers/postcss-config.ts +159 -0
- package/helpers/wp-externals.js +83 -0
- package/helpers/wp-externals.js.map +1 -0
- package/helpers/wp-externals.ts +87 -0
- package/lib/package.json +114 -0
- package/lib/postcss-clean.js +38 -0
- package/lib/postcss-clean.js.map +1 -0
- package/lib/postcss-clean.ts +42 -0
- package/lib/postcss-pretty.js +50 -0
- package/lib/postcss-pretty.js.map +1 -0
- package/lib/postcss-pretty.ts +67 -0
- package/package.json +70 -0
- package/types/css-loader.d.ts +87 -0
- package/types/utility.d.ts +6 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"# js-boilerplate-shared"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const jestConfig = {
|
|
2
|
+
globals: {
|
|
3
|
+
__TEST__: true,
|
|
4
|
+
},
|
|
5
|
+
roots: [
|
|
6
|
+
'./tests',
|
|
7
|
+
],
|
|
8
|
+
transform: {
|
|
9
|
+
'^.+\\.m?[tj]sx?$': ['babel-jest', {
|
|
10
|
+
presets: [
|
|
11
|
+
['@babel/preset-env', { targets: { node: 'current' } }],
|
|
12
|
+
'@babel/preset-typescript',
|
|
13
|
+
],
|
|
14
|
+
plugins: [
|
|
15
|
+
['babel-plugin-transform-import-meta', { module: 'ES6' }],
|
|
16
|
+
],
|
|
17
|
+
}],
|
|
18
|
+
},
|
|
19
|
+
transformIgnorePatterns: [
|
|
20
|
+
'node_modules/(?!@lipemat)',
|
|
21
|
+
],
|
|
22
|
+
moduleNameMapper: {
|
|
23
|
+
'\\.(pcss|less|css)$': 'identity-obj-proxy',
|
|
24
|
+
'is-plain-obj': 'identity-obj-proxy',
|
|
25
|
+
uuid: 'identity-obj-proxy',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
export default jestConfig;
|
|
29
|
+
//# sourceMappingURL=jest.config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jest.config.js","sourceRoot":"","sources":["jest.config.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAW;IAC1B,OAAO,EAAE;QACR,QAAQ,EAAE,IAAI;KACd;IACD,KAAK,EAAE;QACN,SAAS;KACT;IACD,SAAS,EAAE;QACV,kBAAkB,EAAE,CAAE,YAAY,EAAE;gBACnC,OAAO,EAAE;oBACR,CAAE,mBAAmB,EAAE,EAAC,OAAO,EAAE,EAAC,IAAI,EAAE,SAAS,EAAC,EAAC,CAAE;oBACrD,0BAA0B;iBAC1B;gBACD,OAAO,EAAE;oBACR,CAAE,oCAAoC,EAAE,EAAC,MAAM,EAAE,KAAK,EAAC,CAAE;iBACzD;aACD,CAAE;KACH;IACD,uBAAuB,EAAE;QACxB,2BAA2B;KAC3B;IACD,gBAAgB,EAAE;QACjB,qBAAqB,EAAE,oBAAoB;QAC3C,cAAc,EAAE,oBAAoB;QACpC,IAAI,EAAE,oBAAoB;KAC1B;CACD,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type {Config} from 'jest';
|
|
2
|
+
|
|
3
|
+
const jestConfig: Config = {
|
|
4
|
+
globals: {
|
|
5
|
+
__TEST__: true,
|
|
6
|
+
},
|
|
7
|
+
roots: [
|
|
8
|
+
'./tests',
|
|
9
|
+
],
|
|
10
|
+
transform: {
|
|
11
|
+
'^.+\\.m?[tj]sx?$': [ 'babel-jest', {
|
|
12
|
+
presets: [
|
|
13
|
+
[ '@babel/preset-env', {targets: {node: 'current'}} ],
|
|
14
|
+
'@babel/preset-typescript',
|
|
15
|
+
],
|
|
16
|
+
plugins: [
|
|
17
|
+
[ 'babel-plugin-transform-import-meta', {module: 'ES6'} ],
|
|
18
|
+
],
|
|
19
|
+
} ],
|
|
20
|
+
},
|
|
21
|
+
transformIgnorePatterns: [
|
|
22
|
+
'node_modules/(?!@lipemat)',
|
|
23
|
+
],
|
|
24
|
+
moduleNameMapper: {
|
|
25
|
+
'\\.(pcss|less|css)$': 'identity-obj-proxy',
|
|
26
|
+
'is-plain-obj': 'identity-obj-proxy',
|
|
27
|
+
uuid: 'identity-obj-proxy',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default jestConfig;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// @ts-expect-error
|
|
2
|
+
import wpBrowsers from '@wordpress/browserslist-config';
|
|
3
|
+
import browserslist from 'browserslist';
|
|
4
|
+
/**
|
|
5
|
+
* Get the browserslist from the current project.
|
|
6
|
+
*
|
|
7
|
+
* - If specified using standard browserslist config, we will use that.
|
|
8
|
+
*
|
|
9
|
+
* @link https://github.com/browserslist/browserslist#config-file
|
|
10
|
+
*/
|
|
11
|
+
export function getBrowsersList() {
|
|
12
|
+
const projectBrowsersList = browserslist();
|
|
13
|
+
if (browserslist(browserslist.defaults) === projectBrowsersList) {
|
|
14
|
+
return wpBrowsers;
|
|
15
|
+
}
|
|
16
|
+
return projectBrowsersList;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=browserslist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserslist.js","sourceRoot":"","sources":["browserslist.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,OAAO,UAAU,MAAM,gCAAgC,CAAC;AACxD,OAAO,YAAY,MAAM,cAAc,CAAC;AAExC;;;;;;GAMG;AACH,MAAM,UAAU,eAAe;IAC9B,MAAM,mBAAmB,GAAG,YAAY,EAAE,CAAC;IAC3C,IAAK,YAAY,CAAE,YAAY,CAAC,QAAQ,CAAE,KAAK,mBAAmB,EAAG,CAAC;QACrE,OAAO,UAAU,CAAC;IACnB,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// @ts-expect-error
|
|
2
|
+
import wpBrowsers from '@wordpress/browserslist-config';
|
|
3
|
+
import browserslist from 'browserslist';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get the browserslist from the current project.
|
|
7
|
+
*
|
|
8
|
+
* - If specified using standard browserslist config, we will use that.
|
|
9
|
+
*
|
|
10
|
+
* @link https://github.com/browserslist/browserslist#config-file
|
|
11
|
+
*/
|
|
12
|
+
export function getBrowsersList(): readonly string[] {
|
|
13
|
+
const projectBrowsersList = browserslist();
|
|
14
|
+
if ( browserslist( browserslist.defaults ) === projectBrowsersList ) {
|
|
15
|
+
return wpBrowsers;
|
|
16
|
+
}
|
|
17
|
+
return projectBrowsersList;
|
|
18
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a dash/dot/underscore/space separated string to camelCase or PascalCase
|
|
3
|
+
*
|
|
4
|
+
* Inspired by the 'camelcase' npm package, no longer maintained.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import camelCase from '../helpers/camel-case';
|
|
8
|
+
*
|
|
9
|
+
* camelCase('foo-bar');
|
|
10
|
+
* //=> 'fooBar'
|
|
11
|
+
*
|
|
12
|
+
* camelCase('foo_bar');
|
|
13
|
+
* //=> 'fooBar'
|
|
14
|
+
*
|
|
15
|
+
* camelCase('Foo-Bar');
|
|
16
|
+
* //=> 'fooBar'
|
|
17
|
+
*
|
|
18
|
+
* camelCase('Foo-Bar', true);
|
|
19
|
+
* //=> 'FooBar'
|
|
20
|
+
*
|
|
21
|
+
* camelCase('--foo.bar', false);
|
|
22
|
+
* //=> 'fooBar'
|
|
23
|
+
*
|
|
24
|
+
* camelCase('foo bar');
|
|
25
|
+
* //=> 'fooBar'
|
|
26
|
+
*
|
|
27
|
+
* camelCase('--foo-bar');
|
|
28
|
+
* //=> 'fooBar'
|
|
29
|
+
*
|
|
30
|
+
* camelCase(['foo', 'bar']);
|
|
31
|
+
* //=> 'fooBar'
|
|
32
|
+
*
|
|
33
|
+
* camelCase(['__foo__', '--bar'], pascalCase);
|
|
34
|
+
* //=> 'FooBar'
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function preserveCamelCase(string) {
|
|
38
|
+
let isLastCharLower = false;
|
|
39
|
+
let isLastCharUpper = false;
|
|
40
|
+
let isLastLastCharUpper = false;
|
|
41
|
+
for (let i = 0; i < string.length; i++) {
|
|
42
|
+
const character = string[i];
|
|
43
|
+
if (isLastCharLower && /[a-zA-Z]/.test(character) && character.toUpperCase() === character) {
|
|
44
|
+
string = string.slice(0, i) + '-' + string.slice(i);
|
|
45
|
+
isLastCharLower = false;
|
|
46
|
+
isLastLastCharUpper = isLastCharUpper;
|
|
47
|
+
isLastCharUpper = true;
|
|
48
|
+
i++;
|
|
49
|
+
}
|
|
50
|
+
else if (isLastCharUpper && isLastLastCharUpper && /[a-zA-Z]/.test(character) && character.toLowerCase() === character) {
|
|
51
|
+
string = string.slice(0, i - 1) + '-' + string.slice(i - 1);
|
|
52
|
+
isLastLastCharUpper = isLastCharUpper;
|
|
53
|
+
isLastCharUpper = false;
|
|
54
|
+
isLastCharLower = true;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
isLastCharLower = character.toLowerCase() === character && character.toUpperCase() !== character;
|
|
58
|
+
isLastLastCharUpper = isLastCharUpper;
|
|
59
|
+
isLastCharUpper = character.toUpperCase() === character && character.toLowerCase() !== character;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return string;
|
|
63
|
+
}
|
|
64
|
+
export default function camelCase(input, pascalCase = false) {
|
|
65
|
+
let value;
|
|
66
|
+
if ('string' === typeof input) {
|
|
67
|
+
value = input.trim();
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
value = input.map(x => x.trim())
|
|
71
|
+
.filter((item) => item.length > 0)
|
|
72
|
+
.join('-');
|
|
73
|
+
}
|
|
74
|
+
if (0 === value.length) {
|
|
75
|
+
return '';
|
|
76
|
+
}
|
|
77
|
+
if (1 === value.length) {
|
|
78
|
+
return pascalCase ? value.toUpperCase() : value.toLowerCase();
|
|
79
|
+
}
|
|
80
|
+
if (value !== value.toLowerCase()) {
|
|
81
|
+
value = preserveCamelCase(value);
|
|
82
|
+
}
|
|
83
|
+
value = value
|
|
84
|
+
.replace(/^[_.\- ]+/, '')
|
|
85
|
+
.toLowerCase()
|
|
86
|
+
.replace(/[_.\- ]+(\w|$)/g, (_, p1) => p1.toUpperCase())
|
|
87
|
+
.replace(/\d+(\w|$)/g, m => m.toUpperCase());
|
|
88
|
+
if (pascalCase) {
|
|
89
|
+
value = value.charAt(0).toUpperCase() + value.slice(1);
|
|
90
|
+
}
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=camel-case.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camel-case.js","sourceRoot":"","sources":["camel-case.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a dash/dot/underscore/space separated string to camelCase or PascalCase
|
|
3
|
+
*
|
|
4
|
+
* Inspired by the 'camelcase' npm package, no longer maintained.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import camelCase from '../helpers/camel-case';
|
|
8
|
+
*
|
|
9
|
+
* camelCase('foo-bar');
|
|
10
|
+
* //=> 'fooBar'
|
|
11
|
+
*
|
|
12
|
+
* camelCase('foo_bar');
|
|
13
|
+
* //=> 'fooBar'
|
|
14
|
+
*
|
|
15
|
+
* camelCase('Foo-Bar');
|
|
16
|
+
* //=> 'fooBar'
|
|
17
|
+
*
|
|
18
|
+
* camelCase('Foo-Bar', true);
|
|
19
|
+
* //=> 'FooBar'
|
|
20
|
+
*
|
|
21
|
+
* camelCase('--foo.bar', false);
|
|
22
|
+
* //=> 'fooBar'
|
|
23
|
+
*
|
|
24
|
+
* camelCase('foo bar');
|
|
25
|
+
* //=> 'fooBar'
|
|
26
|
+
*
|
|
27
|
+
* camelCase('--foo-bar');
|
|
28
|
+
* //=> 'fooBar'
|
|
29
|
+
*
|
|
30
|
+
* camelCase(['foo', 'bar']);
|
|
31
|
+
* //=> 'fooBar'
|
|
32
|
+
*
|
|
33
|
+
* camelCase(['__foo__', '--bar'], pascalCase);
|
|
34
|
+
* //=> 'FooBar'
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
function preserveCamelCase( string: string ): string {
|
|
39
|
+
let isLastCharLower = false;
|
|
40
|
+
let isLastCharUpper = false;
|
|
41
|
+
let isLastLastCharUpper = false;
|
|
42
|
+
|
|
43
|
+
for ( let i = 0; i < string.length; i++ ) {
|
|
44
|
+
const character = string[ i ];
|
|
45
|
+
|
|
46
|
+
if ( isLastCharLower && /[a-zA-Z]/.test( character ) && character.toUpperCase() === character ) {
|
|
47
|
+
string = string.slice( 0, i ) + '-' + string.slice( i );
|
|
48
|
+
isLastCharLower = false;
|
|
49
|
+
isLastLastCharUpper = isLastCharUpper;
|
|
50
|
+
isLastCharUpper = true;
|
|
51
|
+
i++;
|
|
52
|
+
} else if ( isLastCharUpper && isLastLastCharUpper && /[a-zA-Z]/.test( character ) && character.toLowerCase() === character ) {
|
|
53
|
+
string = string.slice( 0, i - 1 ) + '-' + string.slice( i - 1 );
|
|
54
|
+
isLastLastCharUpper = isLastCharUpper;
|
|
55
|
+
isLastCharUpper = false;
|
|
56
|
+
isLastCharLower = true;
|
|
57
|
+
} else {
|
|
58
|
+
isLastCharLower = character.toLowerCase() === character && character.toUpperCase() !== character;
|
|
59
|
+
isLastLastCharUpper = isLastCharUpper;
|
|
60
|
+
isLastCharUpper = character.toUpperCase() === character && character.toLowerCase() !== character;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
export default function camelCase( input: string | ReadonlyArray<string>, pascalCase: boolean = false ): string {
|
|
69
|
+
let value: string;
|
|
70
|
+
if ( 'string' === typeof input ) {
|
|
71
|
+
value = input.trim();
|
|
72
|
+
} else {
|
|
73
|
+
value = input.map( x => x.trim() )
|
|
74
|
+
.filter( ( item: string ) => item.length > 0 )
|
|
75
|
+
.join( '-' );
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if ( 0 === value.length ) {
|
|
79
|
+
return '';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if ( 1 === value.length ) {
|
|
83
|
+
return pascalCase ? value.toUpperCase() : value.toLowerCase();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if ( value !== value.toLowerCase() ) {
|
|
87
|
+
value = preserveCamelCase( value );
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
value = value
|
|
91
|
+
.replace( /^[_.\- ]+/, '' )
|
|
92
|
+
.toLowerCase()
|
|
93
|
+
.replace( /[_.\- ]+(\w|$)/g, ( _, p1 ) => p1.toUpperCase() )
|
|
94
|
+
.replace( /\d+(\w|$)/g, m => m.toUpperCase() );
|
|
95
|
+
|
|
96
|
+
if ( pascalCase ) {
|
|
97
|
+
value = value.charAt( 0 ).toUpperCase() + value.slice( 1 )
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { getPackageConfig } from './package-config.js';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
const requireModule = createRequire(import.meta.url);
|
|
4
|
+
/**
|
|
5
|
+
* Get a list of installed js-boilerplate extensions.
|
|
6
|
+
*
|
|
7
|
+
* - Exclude @lipemat/js-boilerplate-shared and @lipemat/js-boilerplate
|
|
8
|
+
* as they are libraries not extensions.
|
|
9
|
+
*/
|
|
10
|
+
export function getExtensions() {
|
|
11
|
+
const { dependencies, devDependencies } = getPackageConfig();
|
|
12
|
+
return [...Object.keys(dependencies), ...Object.keys(devDependencies)].filter((extension) => {
|
|
13
|
+
return extension.includes('js-boilerplate-') &&
|
|
14
|
+
extension !== '@lipemat/js-boilerplate-shared' &&
|
|
15
|
+
extension !== '@lipemat/js-boilerplate';
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get a config from any existing extension's /config directories
|
|
20
|
+
* merged into one.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} fileName - Name of the config file to load.
|
|
23
|
+
* @param {Object} defaultConfig - Default config sed for passing to an extension callback.
|
|
24
|
+
*/
|
|
25
|
+
export function getExtensionsConfig(fileName, defaultConfig) {
|
|
26
|
+
let mergedConfig = {};
|
|
27
|
+
for (const extension of getExtensions()) {
|
|
28
|
+
try {
|
|
29
|
+
let extensionConfig = requireModule(extension + '/config/' + fileName);
|
|
30
|
+
// For ES Modules, we need to use the default export.
|
|
31
|
+
if ('default' in extensionConfig) {
|
|
32
|
+
extensionConfig = extensionConfig.default;
|
|
33
|
+
}
|
|
34
|
+
if ('function' === typeof extensionConfig) {
|
|
35
|
+
mergedConfig = { ...mergedConfig, ...extensionConfig({ ...defaultConfig, ...mergedConfig }) };
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
mergedConfig = { ...mergedConfig, ...extensionConfig };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
if (e instanceof Error) {
|
|
43
|
+
if (!('code' in e) || 'MODULE_NOT_FOUND' !== e.code) {
|
|
44
|
+
console.error(e);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return mergedConfig;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Ensure the file extension is .js.
|
|
53
|
+
*/
|
|
54
|
+
export function ensureJSExtension(fileName) {
|
|
55
|
+
const withoutExtension = fileName.replace(/\.(ts|js)$/, '');
|
|
56
|
+
if (!withoutExtension.endsWith('.js')) {
|
|
57
|
+
return withoutExtension + '.js';
|
|
58
|
+
}
|
|
59
|
+
return withoutExtension;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAE1C,MAAM,aAAa,GAAG,aAAa,CAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAE,CAAC;AAGvD;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC5B,MAAM,EAAC,YAAY,EAAE,eAAe,EAAC,GAAG,gBAAgB,EAAE,CAAC;IAE3D,OAAO,CAAE,GAAG,MAAM,CAAC,IAAI,CAAE,YAAY,CAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAE,eAAe,CAAE,CAAE,CAAC,MAAM,CAAE,CAAE,SAAiB,EAAG,EAAE;QAC5G,OAAO,SAAS,CAAC,QAAQ,CAAE,iBAAiB,CAAE;YAC7C,SAAS,KAAK,gCAAgC;YAC9C,SAAS,KAAK,yBAAyB,CAAC;IAC1C,CAAC,CAAE,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAoB,QAAgB,EAAE,aAAgB;IACxF,IAAI,YAAY,GAAM,EAAO,CAAC;IAC9B,KAAM,MAAM,SAAS,IAAI,aAAa,EAAE,EAAG,CAAC;QAC3C,IAAI,CAAC;YACJ,IAAI,eAAe,GAAG,aAAa,CAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAE,CAAC;YACzE,qDAAqD;YACrD,IAAK,SAAS,IAAI,eAAe,EAAG,CAAC;gBACpC,eAAe,GAAG,eAAe,CAAC,OAAO,CAAC;YAC3C,CAAC;YACD,IAAK,UAAU,KAAK,OAAO,eAAe,EAAG,CAAC;gBAC7C,YAAY,GAAG,EAAC,GAAG,YAAY,EAAE,GAAG,eAAe,CAAE,EAAC,GAAG,aAAa,EAAE,GAAG,YAAY,EAAC,CAAE,EAAC,CAAC;YAC7F,CAAC;iBAAM,CAAC;gBACP,YAAY,GAAG,EAAC,GAAG,YAAY,EAAE,GAAG,eAAe,EAAC,CAAC;YACtD,CAAC;QACF,CAAC;QAAC,OAAQ,CAAC,EAAG,CAAC;YACd,IAAK,CAAC,YAAY,KAAK,EAAG,CAAC;gBAC1B,IAAK,CAAE,CAAE,MAAM,IAAI,CAAC,CAAE,IAAI,kBAAkB,KAAK,CAAC,CAAC,IAAI,EAAG,CAAC;oBAC1D,OAAO,CAAC,KAAK,CAAE,CAAC,CAAE,CAAC;gBACpB,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,YAAY,CAAC;AACrB,CAAC;AAGD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAE,QAAgB;IAClD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,OAAO,CAAE,YAAY,EAAE,EAAE,CAAE,CAAC;IAC9D,IAAK,CAAE,gBAAgB,CAAC,QAAQ,CAAE,KAAK,CAAE,EAAG,CAAC;QAC5C,OAAO,gBAAgB,GAAG,KAAK,CAAC;IACjC,CAAC;IACD,OAAO,gBAAgB,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {getPackageConfig} from './package-config.js';
|
|
2
|
+
import {createRequire} from 'node:module';
|
|
3
|
+
|
|
4
|
+
const requireModule = createRequire( import.meta.url );
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get a list of installed js-boilerplate extensions.
|
|
9
|
+
*
|
|
10
|
+
* - Exclude @lipemat/js-boilerplate-shared and @lipemat/js-boilerplate
|
|
11
|
+
* as they are libraries not extensions.
|
|
12
|
+
*/
|
|
13
|
+
export function getExtensions(): readonly string[] {
|
|
14
|
+
const {dependencies, devDependencies} = getPackageConfig();
|
|
15
|
+
|
|
16
|
+
return [ ...Object.keys( dependencies ), ...Object.keys( devDependencies ) ].filter( ( extension: string ) => {
|
|
17
|
+
return extension.includes( 'js-boilerplate-' ) &&
|
|
18
|
+
extension !== '@lipemat/js-boilerplate-shared' &&
|
|
19
|
+
extension !== '@lipemat/js-boilerplate';
|
|
20
|
+
} );
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get a config from any existing extension's /config directories
|
|
25
|
+
* merged into one.
|
|
26
|
+
*
|
|
27
|
+
* @param {string} fileName - Name of the config file to load.
|
|
28
|
+
* @param {Object} defaultConfig - Default config sed for passing to an extension callback.
|
|
29
|
+
*/
|
|
30
|
+
export function getExtensionsConfig<T extends object>( fileName: string, defaultConfig: T ): T {
|
|
31
|
+
let mergedConfig: T = {} as T;
|
|
32
|
+
for ( const extension of getExtensions() ) {
|
|
33
|
+
try {
|
|
34
|
+
let extensionConfig = requireModule( extension + '/config/' + fileName );
|
|
35
|
+
// For ES Modules, we need to use the default export.
|
|
36
|
+
if ( 'default' in extensionConfig ) {
|
|
37
|
+
extensionConfig = extensionConfig.default;
|
|
38
|
+
}
|
|
39
|
+
if ( 'function' === typeof extensionConfig ) {
|
|
40
|
+
mergedConfig = {...mergedConfig, ...extensionConfig( {...defaultConfig, ...mergedConfig} )};
|
|
41
|
+
} else {
|
|
42
|
+
mergedConfig = {...mergedConfig, ...extensionConfig};
|
|
43
|
+
}
|
|
44
|
+
} catch ( e ) {
|
|
45
|
+
if ( e instanceof Error ) {
|
|
46
|
+
if ( ! ( 'code' in e ) || 'MODULE_NOT_FOUND' !== e.code ) {
|
|
47
|
+
console.error( e );
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return mergedConfig;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Ensure the file extension is .js.
|
|
59
|
+
*/
|
|
60
|
+
export function ensureJSExtension( fileName: string ): string {
|
|
61
|
+
const withoutExtension = fileName.replace( /\.(ts|js)$/, '' );
|
|
62
|
+
if ( ! withoutExtension.endsWith( '.js' ) ) {
|
|
63
|
+
return withoutExtension + '.js';
|
|
64
|
+
}
|
|
65
|
+
return withoutExtension;
|
|
66
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { getPackageConfig } from './package-config.js';
|
|
2
|
+
export const SHORT_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
3
|
+
export const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
4
|
+
const classes = {};
|
|
5
|
+
let counters = [-1];
|
|
6
|
+
/**
|
|
7
|
+
* Check if short CSS classes are enabled.
|
|
8
|
+
*
|
|
9
|
+
* Using a helper function to allow for future enhancements.
|
|
10
|
+
*
|
|
11
|
+
* @since 4.6.0
|
|
12
|
+
*/
|
|
13
|
+
export function usingShortCssClasses() {
|
|
14
|
+
const short = getPackageConfig().shortCssClasses;
|
|
15
|
+
if ('object' === typeof short) {
|
|
16
|
+
return Boolean(short.js);
|
|
17
|
+
}
|
|
18
|
+
return Boolean(short);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Reset all counters.
|
|
22
|
+
*
|
|
23
|
+
* @notice Mostly here for unit tests.
|
|
24
|
+
*/
|
|
25
|
+
export function resetCounters() {
|
|
26
|
+
counters = [-1];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the next class in the sequence based on:
|
|
30
|
+
* 1. Single character from SHORT_ALPHABET (prevent conflicts with JS boilerplate).
|
|
31
|
+
* 2. Incremented character from the `ALPHABET`.
|
|
32
|
+
* 1. Used once requires 2+ characters.
|
|
33
|
+
* 2. Grows to 3+ characters as needed.
|
|
34
|
+
*
|
|
35
|
+
* @return {string}
|
|
36
|
+
*/
|
|
37
|
+
export function getNextClass() {
|
|
38
|
+
const last = counters.length - 1;
|
|
39
|
+
let totalLetters = ALPHABET.length - 1;
|
|
40
|
+
// The first level uses the SHORT_ALPHABET.
|
|
41
|
+
if (0 === last) {
|
|
42
|
+
totalLetters = SHORT_ALPHABET.length - 1;
|
|
43
|
+
}
|
|
44
|
+
if (counters[last] < totalLetters) {
|
|
45
|
+
counters[last]++;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
incrementParent();
|
|
49
|
+
}
|
|
50
|
+
return counters.map((counter, i) => {
|
|
51
|
+
return 0 === i ? SHORT_ALPHABET[counter] : ALPHABET[counter];
|
|
52
|
+
}).join('');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* When we run out of characters on the current level:
|
|
56
|
+
* 1. Increment the parent level.
|
|
57
|
+
* 2. Reset the current level and all child levels back to 0.
|
|
58
|
+
*
|
|
59
|
+
* If we are out of characters on the parent level or have
|
|
60
|
+
* no parent level:
|
|
61
|
+
* 1. Add a new child level.
|
|
62
|
+
* 2. Reset all levels back to 0.
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
function incrementParent() {
|
|
66
|
+
let parent = counters.length - 2;
|
|
67
|
+
let totalLetters = ALPHABET.length - 1;
|
|
68
|
+
while (counters[parent] !== undefined) {
|
|
69
|
+
// The first level uses the SHORT_ALPHABET.
|
|
70
|
+
if (0 === parent) {
|
|
71
|
+
totalLetters = SHORT_ALPHABET.length - 1;
|
|
72
|
+
}
|
|
73
|
+
if (counters[parent] < totalLetters) {
|
|
74
|
+
counters[parent]++;
|
|
75
|
+
// Reset all child levels to 0.
|
|
76
|
+
while (counters[parent + 1] !== undefined) {
|
|
77
|
+
counters[parent + 1] = 0;
|
|
78
|
+
parent++;
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
parent--;
|
|
83
|
+
}
|
|
84
|
+
// Add a new level and reset all existing levels.
|
|
85
|
+
counters.forEach((_, i) => counters[i] = 0);
|
|
86
|
+
counters.push(0);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Return a single character unique CSS class name based on WebPack
|
|
90
|
+
* css-loader's `getLocalIdentName` callback.
|
|
91
|
+
*
|
|
92
|
+
* Tracks CSS classes per each file so duplicate uses of the
|
|
93
|
+
* same class in a file receive the same result.
|
|
94
|
+
*
|
|
95
|
+
* @notice Only enabled if the `package.json` has `shortCssClasses` set to true.
|
|
96
|
+
*
|
|
97
|
+
* @link https://webpack.js.org/loaders/css-loader/#getlocalident
|
|
98
|
+
*/
|
|
99
|
+
export const getLocalIdent = ({ resourcePath }, _, localName) => {
|
|
100
|
+
classes[resourcePath] ||= {};
|
|
101
|
+
classes[resourcePath][localName] ||= getNextClass();
|
|
102
|
+
return classes[resourcePath][localName];
|
|
103
|
+
};
|
|
104
|
+
//# sourceMappingURL=css-classnames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-classnames.js","sourceRoot":"","sources":["css-classnames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AAIrD,MAAM,CAAC,MAAM,cAAc,GAAG,4BAA4B,CAAC;AAC3D,MAAM,CAAC,MAAM,QAAQ,GAAG,gEAAgE,CAAC;AAEzF,MAAM,OAAO,GAIT,EAAE,CAAC;AAEP,IAAI,QAAQ,GAAG,CAAE,CAAC,CAAC,CAAE,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB;IACnC,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC,eAAe,CAAC;IACjD,IAAK,QAAQ,KAAK,OAAO,KAAK,EAAG,CAAC;QACjC,OAAO,OAAO,CAAE,KAAK,CAAC,EAAE,CAAE,CAAC;IAC5B,CAAC;IACD,OAAO,OAAO,CAAE,KAAK,CAAE,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC5B,QAAQ,GAAG,CAAE,CAAC,CAAC,CAAE,CAAC;AACnB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY;IAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,IAAI,YAAY,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAEvC,2CAA2C;IAC3C,IAAK,CAAC,KAAK,IAAI,EAAG,CAAC;QAClB,YAAY,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,CAAC;IAED,IAAK,QAAQ,CAAE,IAAI,CAAE,GAAG,YAAY,EAAG,CAAC;QACvC,QAAQ,CAAE,IAAI,CAAE,EAAE,CAAC;IACpB,CAAC;SAAM,CAAC;QACP,eAAe,EAAE,CAAC;IACnB,CAAC;IAED,OAAO,QAAQ,CAAC,GAAG,CAAE,CAAE,OAAO,EAAE,CAAC,EAAG,EAAE;QACrC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAE,OAAO,CAAE,CAAC,CAAC,CAAC,QAAQ,CAAE,OAAO,CAAE,CAAC;IAClE,CAAC,CAAE,CAAC,IAAI,CAAE,EAAE,CAAE,CAAC;AAChB,CAAC;AAGD;;;;;;;;;;GAUG;AACH,SAAS,eAAe;IACvB,IAAI,MAAM,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,IAAI,YAAY,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAEvC,OAAQ,QAAQ,CAAE,MAAM,CAAE,KAAK,SAAS,EAAG,CAAC;QAC3C,2CAA2C;QAC3C,IAAK,CAAC,KAAK,MAAM,EAAG,CAAC;YACpB,YAAY,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1C,CAAC;QACD,IAAK,QAAQ,CAAE,MAAM,CAAE,GAAG,YAAY,EAAG,CAAC;YACzC,QAAQ,CAAE,MAAM,CAAE,EAAE,CAAC;YACrB,+BAA+B;YAC/B,OAAQ,QAAQ,CAAE,MAAM,GAAG,CAAC,CAAE,KAAK,SAAS,EAAG,CAAC;gBAC/C,QAAQ,CAAE,MAAM,GAAG,CAAC,CAAE,GAAG,CAAC,CAAC;gBAC3B,MAAM,EAAE,CAAC;YACV,CAAC;YACD,OAAO;QACR,CAAC;QACD,MAAM,EAAE,CAAC;IACV,CAAC;IAED,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAE,CAAE,CAAC,EAAE,CAAC,EAAG,EAAE,CAAC,QAAQ,CAAE,CAAC,CAAE,GAAG,CAAC,CAAE,CAAC;IAClD,QAAQ,CAAC,IAAI,CAAE,CAAC,CAAE,CAAC;AACpB,CAAC;AAID;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAE,EAAC,YAAY,EAA+C,EAAE,CAAsB,EAAE,SAA8B,EAA8B,EAAE;IAClL,OAAO,CAAE,YAAY,CAAE,KAAK,EAAE,CAAC;IAC/B,OAAO,CAAE,YAAY,CAAE,CAAE,SAAS,CAAE,KAAK,YAAY,EAAE,CAAC;IACxD,OAAO,OAAO,CAAE,YAAY,CAAE,CAAE,SAAS,CAAE,CAAC;AAC7C,CAAC,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {getPackageConfig} from './package-config.js';
|
|
2
|
+
import type {GetLocalIdent} from '../types/css-loader.ts';
|
|
3
|
+
import type {AtLeast} from '../types/utility.ts';
|
|
4
|
+
|
|
5
|
+
export const SHORT_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
6
|
+
export const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
7
|
+
|
|
8
|
+
const classes: {
|
|
9
|
+
[ filename: string ]: {
|
|
10
|
+
[ className: string ]: string
|
|
11
|
+
}
|
|
12
|
+
} = {};
|
|
13
|
+
|
|
14
|
+
let counters = [ -1 ];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Check if short CSS classes are enabled.
|
|
18
|
+
*
|
|
19
|
+
* Using a helper function to allow for future enhancements.
|
|
20
|
+
*
|
|
21
|
+
* @since 4.6.0
|
|
22
|
+
*/
|
|
23
|
+
export function usingShortCssClasses(): boolean {
|
|
24
|
+
const short = getPackageConfig().shortCssClasses;
|
|
25
|
+
if ( 'object' === typeof short ) {
|
|
26
|
+
return Boolean( short.js );
|
|
27
|
+
}
|
|
28
|
+
return Boolean( short );
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Reset all counters.
|
|
33
|
+
*
|
|
34
|
+
* @notice Mostly here for unit tests.
|
|
35
|
+
*/
|
|
36
|
+
export function resetCounters(): void {
|
|
37
|
+
counters = [ -1 ];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the next class in the sequence based on:
|
|
42
|
+
* 1. Single character from SHORT_ALPHABET (prevent conflicts with JS boilerplate).
|
|
43
|
+
* 2. Incremented character from the `ALPHABET`.
|
|
44
|
+
* 1. Used once requires 2+ characters.
|
|
45
|
+
* 2. Grows to 3+ characters as needed.
|
|
46
|
+
*
|
|
47
|
+
* @return {string}
|
|
48
|
+
*/
|
|
49
|
+
export function getNextClass(): string {
|
|
50
|
+
const last = counters.length - 1;
|
|
51
|
+
let totalLetters = ALPHABET.length - 1;
|
|
52
|
+
|
|
53
|
+
// The first level uses the SHORT_ALPHABET.
|
|
54
|
+
if ( 0 === last ) {
|
|
55
|
+
totalLetters = SHORT_ALPHABET.length - 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if ( counters[ last ] < totalLetters ) {
|
|
59
|
+
counters[ last ]++;
|
|
60
|
+
} else {
|
|
61
|
+
incrementParent();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return counters.map( ( counter, i ) => {
|
|
65
|
+
return 0 === i ? SHORT_ALPHABET[ counter ] : ALPHABET[ counter ];
|
|
66
|
+
} ).join( '' );
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* When we run out of characters on the current level:
|
|
72
|
+
* 1. Increment the parent level.
|
|
73
|
+
* 2. Reset the current level and all child levels back to 0.
|
|
74
|
+
*
|
|
75
|
+
* If we are out of characters on the parent level or have
|
|
76
|
+
* no parent level:
|
|
77
|
+
* 1. Add a new child level.
|
|
78
|
+
* 2. Reset all levels back to 0.
|
|
79
|
+
*
|
|
80
|
+
*/
|
|
81
|
+
function incrementParent() {
|
|
82
|
+
let parent = counters.length - 2;
|
|
83
|
+
let totalLetters = ALPHABET.length - 1;
|
|
84
|
+
|
|
85
|
+
while ( counters[ parent ] !== undefined ) {
|
|
86
|
+
// The first level uses the SHORT_ALPHABET.
|
|
87
|
+
if ( 0 === parent ) {
|
|
88
|
+
totalLetters = SHORT_ALPHABET.length - 1;
|
|
89
|
+
}
|
|
90
|
+
if ( counters[ parent ] < totalLetters ) {
|
|
91
|
+
counters[ parent ]++;
|
|
92
|
+
// Reset all child levels to 0.
|
|
93
|
+
while ( counters[ parent + 1 ] !== undefined ) {
|
|
94
|
+
counters[ parent + 1 ] = 0;
|
|
95
|
+
parent++;
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
parent--;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Add a new level and reset all existing levels.
|
|
103
|
+
counters.forEach( ( _, i ) => counters[ i ] = 0 );
|
|
104
|
+
counters.push( 0 );
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
type LocalIdentParams = Parameters<GetLocalIdent>;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Return a single character unique CSS class name based on WebPack
|
|
111
|
+
* css-loader's `getLocalIdentName` callback.
|
|
112
|
+
*
|
|
113
|
+
* Tracks CSS classes per each file so duplicate uses of the
|
|
114
|
+
* same class in a file receive the same result.
|
|
115
|
+
*
|
|
116
|
+
* @notice Only enabled if the `package.json` has `shortCssClasses` set to true.
|
|
117
|
+
*
|
|
118
|
+
* @link https://webpack.js.org/loaders/css-loader/#getlocalident
|
|
119
|
+
*/
|
|
120
|
+
export const getLocalIdent = ( {resourcePath}: AtLeast<LocalIdentParams[0], 'resourcePath'>, _: LocalIdentParams[1], localName: LocalIdentParams[2] ): ReturnType<GetLocalIdent> => {
|
|
121
|
+
classes[ resourcePath ] ||= {};
|
|
122
|
+
classes[ resourcePath ][ localName ] ||= getNextClass();
|
|
123
|
+
return classes[ resourcePath ][ localName ];
|
|
124
|
+
};
|