Skip to content

Commit

Permalink
Adds prefix & suffix options. Adds guard for numeric characters in al…
Browse files Browse the repository at this point in the history
…phabet. Updates README.md.
  • Loading branch information
unematiii committed Sep 29, 2020
1 parent 518142b commit 504a98f
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 14 deletions.
31 changes: 24 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# css-loader-short-classnames

# A short class name generator for css-loader with CSS Modules enabled.

## Description
Save some extra bytes on your final bundle by shortening class names from something like `[local]-[hash:base64:8]` down to `a` ... `z` ... `A` ... `Z` ... `aA` ... `ZZ` etc.

This package provides class name generator factory with default alphabet `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`. Produced generator function always starts out with single letter character from the beginning of the alphabet and keeps increasing it while at the same time guaranteeing the uniqueness of the class names.
This package provides class name generator factory with default alphabet of `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`. Produced generator function always starts out with single letter character from the beginning of the alphabet and keeps increasing it while at the same time guaranteeing the uniqueness of the class names.

## Install

Expand All @@ -18,7 +19,7 @@ npm i css-loader-shorter-classnames -D
// Import class name generator factory
const { getLocalIdentName } = require('css-loader-shorter-classnames');
// Create generator (should be unique for each entry point)
// Create generator
const getLocalIdent = getLocalIdentName();
// Supply created function as a loader options argument
Expand Down Expand Up @@ -52,16 +53,32 @@ const isProduction = process.env.NODE_ENV === 'production';
},
```

## Custom alphabet
Optionally supply a custom alphabet.
## Custom alphabet, prefix and suffix
Optionally supply a custom alphabet and/or prefix and/or suffix.

NB! Watch out for numbers, spaces, and other invalid characters. Generator does not NOT guarantee that supplied character from alphabet, if number, will not end up as the first character of the class name.
```
const generator = (alphabet? = defaultAlphabet, prefix?: string, suffix?: string) => string;
```

NB! Watch out for spaces and other invalid characters. If alphabet contains numbers, class names that would otherwise start with a number, will be automatically prefixed with `_` (eg `0` --> `_0`)). That is, unless you supply a prefix that doesn't start with a number yourself.

```
const { getLocalIdentName } = require('css-loader-shorter-classnames');
const { classNamesAlphabet, getLocalIdentName } = require('css-loader-shorter-classnames');
// Produces class names like 'a', 'b', 'c', 'aa, 'ab', ..... 'abcabca' etc.
// Produces: 'a', 'b', 'c', 'aa', 'ab', ... 'abcabca' etc.
const getLocalIdent = getLocalIdentName('abc');
// Produces: 'a', 'b', ..., '_0', '_1', ..., '_0a', ..., 'aa', 'a0', ... 'aZ' etc.
const getLocalIdent = getLocalIdentName(classNamesAlphabet.concat('0123456789'));
// Produces: '_a', '_b', ... '_0', ... '_aZ' etc.
const getLocalIdent = getLocalIdentName(classNamesAlphabet.concat('0123456789'), '_');
// Produces: '_000a', '_000b', ... '_0000', ... '_000aZ' etc.
const getLocalIdent = getLocalIdentName(classNamesAlphabet.concat('0123456789'), '000');
// Produces: '_a_', '_b_', ... '_aZ_' etc.
const getLocalIdent = getLocalIdentName(classNamesAlphabet, '_', '_');
```

## Usage with Vue CLI generated projects
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "css-loader-shorter-classnames",
"version": "1.0.1",
"version": "1.0.2",
"description": "Provides short class name generator for css-loader with CSS Modules enabled",
"main": "index.js",
"files": [
Expand All @@ -22,9 +22,10 @@
},
"keywords": [
"css",
"CSSModules",
"css-loader",
"mini-css-extract-plugin"
"css-modules",
"mini-css-extract-plugin",
"vue-cli"
],
"author": "Mati Kärner",
"license": "Apache-2.0",
Expand Down
37 changes: 33 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,46 @@ export type ClassNameGenerator = (
export const classNamesAlphabet =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

const containsNumbers = (input: string) => /\d/.test(input);

const createGenerator = (
alphabet: string = classNamesAlphabet,
prefix?: string,
suffix?: string
) => {
const generator = incstr.idGenerator({ alphabet, prefix, suffix });

const hasNumericAlphabet = containsNumbers(
(!!prefix && alphabet.concat(prefix.charAt(0))) || alphabet
);
const hasNumberSafePrefix = !!prefix && !containsNumbers(prefix.charAt(0));

if (hasNumericAlphabet && !hasNumberSafePrefix) {
return () => {
const className = generator();
return containsNumbers(className.charAt(0)) ? `_${className}` : className;
};
}

return generator;
};

export const getLocalIdentName = (
alphabet: string = classNamesAlphabet
alphabet: string = classNamesAlphabet,
prefix?: string,
suffix?: string
): ClassNameGenerator => {
const classes: Record<string, Record<string, string>> = {};
const classNameGenerator = incstr.idGenerator({ alphabet });
const classNameGenerator = createGenerator(alphabet, prefix, suffix);
const getClassName = (path: string, localName: string): string => {
classes[path] ||= {};
classes[path][localName] ||= classNameGenerator();
return classes[path][localName];
};

return ({ resourcePath }: WebpackLoaderContext, _: string, localName: string) =>
getClassName(resourcePath, localName);
return (
{ resourcePath }: WebpackLoaderContext,
_: string,
localName: string
) => getClassName(resourcePath, localName);
};

0 comments on commit 504a98f

Please sign in to comment.