Skip to content

Commit 928db7b

Browse files
author
Michael Vurchio
committed
Merge branch 'escape-path'
2 parents a8bbe26 + 75ce758 commit 928db7b

File tree

5 files changed

+50
-12
lines changed

5 files changed

+50
-12
lines changed

index.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
const path = require('path')
2-
const { interpolateName } = require('loader-utils')
1+
const path = require('path');
2+
const cssesc = require('cssesc');
3+
const { interpolateName } = require('loader-utils');
34

45
const pluginOptions = {
56
includePaths: [],
67
localIdentName: '[local]-[hash:base64:6]'
7-
}
8+
};
89

910
const regex = {
1011
module: /\$(style)?\.(:?[\w\d-]*)/gm,
1112
style: /<style(\s[^]*?)?>([^]*?)<\/style>/gi,
13+
pathUnallowed: /[<>:"/\\|?*]/g,
1214
class: (className) => {
1315
return new RegExp(`\\.(${className})\\b(?![-_])`, 'gm')
1416
}
@@ -17,27 +19,35 @@ const regex = {
1719
let moduleClasses = {};
1820

1921
function generateName(resourcePath, styles, className) {
20-
const filePath = resourcePath
21-
const fileName = path.basename(filePath)
22+
const filePath = resourcePath;
23+
const fileName = path.basename(filePath);
2224
const localName = pluginOptions.localIdentName.length
2325
? pluginOptions.localIdentName.replace(/\[local\]/gi, () => className)
24-
: className
26+
: className;
2527

26-
const content = `${styles}-${filePath}-${fileName}-${className}`
28+
const content = `${styles}-${filePath}-${fileName}-${className}`;
2729

28-
let interpolatedName = interpolateName({ resourcePath }, localName, { content })
30+
let interpolatedName = cssesc(
31+
interpolateName({ resourcePath }, localName, { content })
32+
.replace(/\./g, '-')
33+
);
34+
35+
// replace unwanted characters from [path]
36+
if (regex.pathUnallowed.test(interpolatedName)) {
37+
interpolatedName = interpolatedName.replace(regex.pathUnallowed, '_');
38+
}
2939

3040
// prevent class error when the generated classname starts from a non word charater
3141
if (/^(?![a-zA-Z_])/.test(interpolatedName)) {
32-
interpolatedName = `_${interpolatedName}`
42+
interpolatedName = `_${interpolatedName}`;
3343
}
3444

3545
// prevent svelte "Unused CSS selector" warning when the generated classname ends by `-`
3646
if (interpolatedName.slice(-1) === '-') {
37-
interpolatedName = interpolatedName.slice(0, -1)
47+
interpolatedName = interpolatedName.slice(0, -1);
3848
}
3949

40-
return interpolatedName
50+
return interpolatedName;
4151
}
4252

4353
const markup = async ({ content, filename }) => {

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"url": "https://github.com/micantoine/svelte-preprocess-cssmodules.git"
2828
},
2929
"dependencies": {
30+
"cssesc": "^3.0.0",
3031
"loader-utils": "^2.0.0"
3132
},
3233
"devDependencies": {

test/compiler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = async ({ source, localIdentName }) => {
99
localIdentName,
1010
})
1111
],
12-
{ filename : 'App.svelte' }
12+
{ filename : 'src/App.svelte' }
1313
);
1414

1515
return code;

test/path.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const compiler = require('./compiler.js');
2+
3+
const source = '<style>.red { color: red; }</style>\n<span class="$style.red">Red</span>';
4+
const sourceReactiveClass = '<style>.red { color: red; }</style>\n<span class:$.red={true}>Red</span>';
5+
6+
test('Replace path on regular class', async () => {
7+
const output = await compiler({
8+
source,
9+
localIdentName: '[path][name]__[local]',
10+
});
11+
12+
expect(output).toBe('<style>:global(.src_App__red) { color: red; }</style>\n<span class="src_App__red">Red</span>');
13+
});
14+
15+
test('Replace path on reactive class', async () => {
16+
const output = await compiler({
17+
source: sourceReactiveClass,
18+
localIdentName: '[path][name]__[local]',
19+
});
20+
21+
expect(output).toBe('<style>:global(.src_App__red) { color: red; }</style>\n<span class:src_App__red={true}>Red</span>');
22+
});

0 commit comments

Comments
 (0)