Skip to content

Commit

Permalink
add cssHash option (#6026)
Browse files Browse the repository at this point in the history
* Allow to customize the css scope class

* Pass component name to scope class generator

* Move Stylesheet arguments into an object

* Refactor to cssHash

* Please the almighty linter

* pass hash function to cssHash

* update test

* document cssHash option

Co-authored-by: Christian Kaisermann <christian@kaisermann.me>
  • Loading branch information
Rich Harris and kaisermann committed Feb 25, 2021
1 parent 5c8807e commit 2925a00
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 9 deletions.
1 change: 1 addition & 0 deletions site/content/docs/04-compile-time.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ The following options can be passed to the compiler. None are required:
| `customElement` | `false` | If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component.
| `tag` | `null` | A `string` that tells Svelte what tag name to register the custom element with. It must be a lowercase alphanumeric string with at least one hyphen, e.g. `"my-element"`.
| `css` | `true` | If `true`, styles will be included in the JavaScript class and injected at runtime. It's recommended that you set this to `false` and use the CSS that is statically generated, as it will result in smaller JavaScript bundles and better performance.
| `cssHash` | See right | A function that takes a `{ hash, css, name, filename }` argument and returns the string that is used as a classname for scoped CSS. It defaults to returning `svelte-${hash(css)}`
| `loopGuardTimeout` | 0 | A `number` that tells Svelte to break the loop if it blocks the thread for more than `loopGuardTimeout` ms. This is useful to prevent infinite loops. **Only available when `dev: true`**
| `preserveComments` | `false` | If `true`, your HTML comments will be preserved during server-side rendering. By default, they are stripped out.
| `preserveWhitespace` | `false` | If `true`, whitespace inside and between elements is kept as you typed it, rather than removed or collapsed to a single space where possible.
Expand Down
10 changes: 6 additions & 4 deletions src/compiler/compile/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,14 @@ export default class Component {
this.locate = getLocator(this.source, { offsetLine: 1 });

// styles
this.stylesheet = new Stylesheet(
this.stylesheet = new Stylesheet({
source,
ast,
compile_options.filename,
compile_options.dev
);
filename: compile_options.filename,
component_name: name,
dev: compile_options.dev,
get_css_hash: compile_options.cssHash
});
this.stylesheet.validate(this);

this.component_options = process_component_options(
Expand Down
29 changes: 26 additions & 3 deletions src/compiler/compile/css/Stylesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import MagicString from 'magic-string';
import { walk } from 'estree-walker';
import Selector from './Selector';
import Element from '../nodes/Element';
import { Ast } from '../../interfaces';
import { Ast, CssHashGetter } from '../../interfaces';
import Component from '../Component';
import { CssNode } from './interfaces';
import hash from '../utils/hash';
Expand Down Expand Up @@ -275,6 +275,10 @@ class Atrule {
}
}

const get_default_css_hash: CssHashGetter = ({ css, hash }) => {
return `svelte-${hash(css)}`;
};

export default class Stylesheet {
source: string;
ast: Ast;
Expand All @@ -289,14 +293,33 @@ export default class Stylesheet {

nodes_with_css_class: Set<CssNode> = new Set();

constructor(source: string, ast: Ast, filename: string, dev: boolean) {
constructor({
source,
ast,
component_name,
filename,
dev,
get_css_hash = get_default_css_hash
}: {
source: string;
ast: Ast;
filename: string | undefined;
component_name: string | undefined;
dev: boolean;
get_css_hash: CssHashGetter;
}) {
this.source = source;
this.ast = ast;
this.filename = filename;
this.dev = dev;

if (ast.css && ast.css.children.length) {
this.id = `svelte-${hash(ast.css.content.styles)}`;
this.id = get_css_hash({
filename,
name: component_name,
css: ast.css.content.styles,
hash
});

this.has_styles = true;

Expand Down
3 changes: 2 additions & 1 deletion src/compiler/compile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const valid_options = [
'css',
'loopGuardTimeout',
'preserveComments',
'preserveWhitespace'
'preserveWhitespace',
'cssHash'
];

function validate_options(options: CompileOptions, warnings: Warning[]) {
Expand Down
10 changes: 9 additions & 1 deletion src/compiler/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ export interface Warning {

export type ModuleFormat = 'esm' | 'cjs';

export type CssHashGetter = (args: {
name: string;
filename: string | undefined;
css: string;
hash: (input: string) => string;
}) => string;

export interface CompileOptions {
format?: ModuleFormat;
name?: string;
Expand All @@ -125,6 +132,7 @@ export interface CompileOptions {
css?: boolean;
loopGuardTimeout?: number;
namespace?: string;
cssHash?: CssHashGetter;

preserveComments?: boolean;
preserveWhitespace?: boolean;
Expand Down Expand Up @@ -166,7 +174,7 @@ export interface Var {
imported?: boolean;
}

export interface CssResult {
export interface CssResult {
code: string;
map: SourceMap;
}
12 changes: 12 additions & 0 deletions test/css/samples/custom-css-hash/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default {
compileOptions: {
filename: 'src/components/FooSwitcher.svelte',
cssHash({ hash, css, name, filename }) {
const minFilename = filename
.split('/')
.map(i => i.charAt(0).toLowerCase())
.join('');
return `sv-${name}-${minFilename}-${hash(css)}`;
}
}
};
1 change: 1 addition & 0 deletions test/css/samples/custom-css-hash/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
div.sv-FooSwitcher-scf-bzh57p{color:red}
7 changes: 7 additions & 0 deletions test/css/samples/custom-css-hash/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div>red</div>

<style>
div {
color: red;
}
</style>

0 comments on commit 2925a00

Please sign in to comment.