mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-17 19:13:34 +08:00
refactor(@angular-devkit/build-angular): remove support for Stylus
The usage of Stylus in the CLI is minimal and this package never reached version 1. BREAKING CHANGE: Deprecated support for Stylus has been removed. The Stylus package has never reached a stable version and its usage in the Angular CLI is minimal. It's recommended to migrate to another CSS preprocessor that the Angular CLI supports.
This commit is contained in:
parent
12931ba8c3
commit
2ba44a433c
@ -8,7 +8,6 @@ digraph G {
|
|||||||
"*.css" -> "postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer";
|
"*.css" -> "postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer";
|
||||||
"*.scss\|sass" -> "sass-loader" -> "postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer";
|
"*.scss\|sass" -> "sass-loader" -> "postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer";
|
||||||
"*.less" -> "less-loader" -> "postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer";
|
"*.less" -> "less-loader" -> "postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer";
|
||||||
"*.styl" -> "stylus-loader" -> "postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer";
|
|
||||||
"postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer" -> "raw-loader, ./optimize-css-webpack-plugin.ts" [label="component style?"];
|
"postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer" -> "raw-loader, ./optimize-css-webpack-plugin.ts" [label="component style?"];
|
||||||
"raw-loader" -> "./optimize-css-webpack-plugin.ts"
|
"raw-loader" -> "./optimize-css-webpack-plugin.ts"
|
||||||
"postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer" -> "style-loader, ./raw-css-loader.ts, and mini-css-extract-plugin" [label="global style?"];
|
"postcss-loader with postcss-import, ./postcss-cli-resources.ts, autoprefixer" -> "style-loader, ./raw-css-loader.ts, and mini-css-extract-plugin" [label="global style?"];
|
||||||
|
@ -54,8 +54,8 @@ This is used for conditional loading of code at build time.
|
|||||||
Two types of stylesheets are used in the build system: global stylesheets and component stylesheets.
|
Two types of stylesheets are used in the build system: global stylesheets and component stylesheets.
|
||||||
Global stylesheets are injected into the `index.html` file, while component stylesheets are loaded directly into compiled Angular components.
|
Global stylesheets are injected into the `index.html` file, while component stylesheets are loaded directly into compiled Angular components.
|
||||||
|
|
||||||
The build system supports plain CSS stylesheets as well as the Sass, LESS and Stylus CSS pre-processors.
|
The build system supports plain CSS stylesheets as well as the Sass and LESS CSS pre-processors.
|
||||||
Stylesheet processing functionality is provided by `sass-loader`, `less-loader`, `stylus-loader`, `postcss-loader`, `postcss-import`, augmented in the build system by custom webpack plugins.
|
Stylesheet processing functionality is provided by `sass-loader`, `less-loader`, `postcss-loader`, `postcss-import`, augmented in the build system by custom webpack plugins.
|
||||||
|
|
||||||
### Assets
|
### Assets
|
||||||
|
|
||||||
|
@ -204,8 +204,6 @@
|
|||||||
"source-map-loader": "4.0.0",
|
"source-map-loader": "4.0.0",
|
||||||
"source-map-support": "0.5.21",
|
"source-map-support": "0.5.21",
|
||||||
"spdx-satisfies": "^5.0.0",
|
"spdx-satisfies": "^5.0.0",
|
||||||
"stylus": "0.59.0",
|
|
||||||
"stylus-loader": "7.0.0",
|
|
||||||
"symbol-observable": "4.0.0",
|
"symbol-observable": "4.0.0",
|
||||||
"tar": "^6.1.6",
|
"tar": "^6.1.6",
|
||||||
"terser": "5.15.0",
|
"terser": "5.15.0",
|
||||||
|
@ -170,8 +170,6 @@ ts_library(
|
|||||||
"@npm//semver",
|
"@npm//semver",
|
||||||
"@npm//source-map-loader",
|
"@npm//source-map-loader",
|
||||||
"@npm//source-map-support",
|
"@npm//source-map-support",
|
||||||
"@npm//stylus",
|
|
||||||
"@npm//stylus-loader",
|
|
||||||
"@npm//terser",
|
"@npm//terser",
|
||||||
"@npm//text-table",
|
"@npm//text-table",
|
||||||
"@npm//tree-kill",
|
"@npm//tree-kill",
|
||||||
|
@ -57,8 +57,6 @@
|
|||||||
"semver": "7.3.7",
|
"semver": "7.3.7",
|
||||||
"source-map-loader": "4.0.0",
|
"source-map-loader": "4.0.0",
|
||||||
"source-map-support": "0.5.21",
|
"source-map-support": "0.5.21",
|
||||||
"stylus": "0.59.0",
|
|
||||||
"stylus-loader": "7.0.0",
|
|
||||||
"terser": "5.15.0",
|
"terser": "5.15.0",
|
||||||
"text-table": "0.2.0",
|
"text-table": "0.2.0",
|
||||||
"tree-kill": "1.2.2",
|
"tree-kill": "1.2.2",
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
"input": {
|
"input": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file to include.",
|
"description": "The file to include.",
|
||||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
"pattern": "\\.(?:css|scss|sass|less)$"
|
||||||
},
|
},
|
||||||
"bundleName": {
|
"bundleName": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -91,7 +91,7 @@
|
|||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file to include.",
|
"description": "The file to include.",
|
||||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
"pattern": "\\.(?:css|scss|sass|less)$"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
"input": {
|
"input": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file to include.",
|
"description": "The file to include.",
|
||||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
"pattern": "\\.(?:css|scss|sass|less)$"
|
||||||
},
|
},
|
||||||
"bundleName": {
|
"bundleName": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -91,7 +91,7 @@
|
|||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file to include.",
|
"description": "The file to include.",
|
||||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
"pattern": "\\.(?:css|scss|sass|less)$"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ import { dirname } from 'path';
|
|||||||
import { browserBuild, createArchitect, host } from '../../../testing/test-utils';
|
import { browserBuild, createArchitect, host } from '../../../testing/test-utils';
|
||||||
|
|
||||||
describe('Browser Builder styles', () => {
|
describe('Browser Builder styles', () => {
|
||||||
const extensionsWithImportSupport = ['css', 'scss', 'less', 'styl'];
|
const extensionsWithImportSupport = ['css', 'scss', 'less'];
|
||||||
const extensionsWithVariableSupport = ['scss', 'less', 'styl'];
|
const extensionsWithVariableSupport = ['scss', 'less'];
|
||||||
const imgSvg = `
|
const imgSvg = `
|
||||||
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
|
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
|
||||||
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
|
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
|
||||||
@ -223,9 +223,6 @@ describe('Browser Builder styles', () => {
|
|||||||
if (ext === 'scss') {
|
if (ext === 'scss') {
|
||||||
variableAssignment = '$primary-color:';
|
variableAssignment = '$primary-color:';
|
||||||
variablereference = '$primary-color';
|
variablereference = '$primary-color';
|
||||||
} else if (ext === 'styl') {
|
|
||||||
variableAssignment = '$primary-color =';
|
|
||||||
variablereference = '$primary-color';
|
|
||||||
} else if (ext === 'less') {
|
} else if (ext === 'less') {
|
||||||
variableAssignment = '@primary-color:';
|
variableAssignment = '@primary-color:';
|
||||||
variablereference = '@primary-color';
|
variablereference = '@primary-color';
|
||||||
|
@ -13,7 +13,7 @@ import { Type } from '../../schema';
|
|||||||
import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup';
|
import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup';
|
||||||
|
|
||||||
describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
|
describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
|
||||||
const CSS_EXTENSIONS = ['css', 'scss', 'less', 'styl'];
|
const CSS_EXTENSIONS = ['css', 'scss', 'less'];
|
||||||
const BUDGET_NOT_MET_REGEXP = /Budget .+ was not met by/;
|
const BUDGET_NOT_MET_REGEXP = /Budget .+ was not met by/;
|
||||||
|
|
||||||
describe('Option: "bundleBudgets"', () => {
|
describe('Option: "bundleBudgets"', () => {
|
||||||
|
@ -58,29 +58,6 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
|
|||||||
harness.expectFile('dist/main.js').content.toContain('color: green');
|
harness.expectFile('dist/main.js').content.toContain('color: green');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Stylus currently does not function due to the sourcemap logic within the `stylus-loader`
|
|
||||||
// which tries to read each stylesheet directly from disk. In this case, each stylesheet is
|
|
||||||
// virtual and cannot be read from disk. This issue affects data URIs in general.
|
|
||||||
// xit('supports Stylus inline component styles when set to "stylus"', async () => {
|
|
||||||
// harness.useTarget('build', {
|
|
||||||
// ...BASE_OPTIONS,
|
|
||||||
// inlineStyleLanguage: InlineStyleLanguage.Stylus,
|
|
||||||
// aot,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// await harness.modifyFile('src/app/app.component.ts', (content) =>
|
|
||||||
// content.replace(
|
|
||||||
// '__STYLE_MARKER__',
|
|
||||||
// '$primary = green;\\nh1 { color: $primary; }',
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const { result } = await harness.executeOnce();
|
|
||||||
|
|
||||||
// expect(result?.success).toBe(true);
|
|
||||||
// harness.expectFile('dist/main.js').content.toContain('color: green');
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('supports Less inline component styles when set to "less"', async () => {
|
it('supports Less inline component styles when set to "less"', async () => {
|
||||||
harness.useTarget('build', {
|
harness.useTarget('build', {
|
||||||
...BASE_OPTIONS,
|
...BASE_OPTIONS,
|
||||||
|
@ -224,7 +224,7 @@ export async function execute(
|
|||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.(css|scss|sass|styl|less)$/,
|
test: /\.(css|scss|sass|less)$/,
|
||||||
loader: require.resolve('./empty-loader'),
|
loader: require.resolve('./empty-loader'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
"input": {
|
"input": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file to include.",
|
"description": "The file to include.",
|
||||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
"pattern": "\\.(?:css|scss|sass|less)$"
|
||||||
},
|
},
|
||||||
"bundleName": {
|
"bundleName": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -95,7 +95,7 @@
|
|||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file to include.",
|
"description": "The file to include.",
|
||||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
"pattern": "\\.(?:css|scss|sass|less)$"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -101,13 +101,6 @@ export function getStylesConfig(wco: WebpackConfigOptions): Configuration {
|
|||||||
extraPlugins.push(new RemoveHashPlugin({ chunkNames: noInjectNames, hashFormat }));
|
extraPlugins.push(new RemoveHashPlugin({ chunkNames: noInjectNames, hashFormat }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalStylePaths.some((p) => p.endsWith('.styl'))) {
|
|
||||||
wco.logger.warn(
|
|
||||||
'Stylus usage is deprecated and will be removed in a future major version. ' +
|
|
||||||
'To opt-out of the deprecated behaviour, please migrate to another stylesheet language.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const sassImplementation = new SassWorkerImplementation();
|
const sassImplementation = new SassWorkerImplementation();
|
||||||
const sassTildeUsageMessage = new Set<string>();
|
const sassTildeUsageMessage = new Set<string>();
|
||||||
|
|
||||||
@ -366,22 +359,6 @@ export function getStylesConfig(wco: WebpackConfigOptions): Configuration {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
extensions: ['styl'],
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: require.resolve('stylus-loader'),
|
|
||||||
options: {
|
|
||||||
sourceMap: cssSourceMap,
|
|
||||||
stylusOptions: {
|
|
||||||
compress: false,
|
|
||||||
sourceMap: { comment: false },
|
|
||||||
paths: includePaths,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -47,7 +47,7 @@ export class AnyComponentStyleBudgetChecker {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cssExtensions = ['.css', '.scss', '.less', '.styl', '.sass'];
|
const cssExtensions = ['.css', '.scss', '.less', '.sass'];
|
||||||
|
|
||||||
const componentStyles = Object.keys(compilation.assets)
|
const componentStyles = Object.keys(compilation.assets)
|
||||||
.filter((name) => cssExtensions.includes(path.extname(name)))
|
.filter((name) => cssExtensions.includes(path.extname(name)))
|
||||||
|
@ -52,7 +52,7 @@ export class CssOptimizerPlugin {
|
|||||||
|
|
||||||
logger.time('optimize css assets');
|
logger.time('optimize css assets');
|
||||||
for (const assetName of Object.keys(compilationAssets)) {
|
for (const assetName of Object.keys(compilationAssets)) {
|
||||||
if (!/\.(?:css|scss|sass|less|styl)$/.test(assetName)) {
|
if (!/\.(?:css|scss|sass|less)$/.test(assetName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,17 +18,6 @@ export default async function () {
|
|||||||
@import 'variables';
|
@import 'variables';
|
||||||
h2 { background-color: $primary-color; }
|
h2 { background-color: $primary-color; }
|
||||||
`,
|
`,
|
||||||
'src/style-paths/variables.styl': '$primary-color = green',
|
|
||||||
'src/styles.styl': `
|
|
||||||
@import 'variables'
|
|
||||||
h3
|
|
||||||
color: $primary-color
|
|
||||||
`,
|
|
||||||
'src/app/app.component.styl': `
|
|
||||||
@import 'variables'
|
|
||||||
h4
|
|
||||||
background-color: $primary-color
|
|
||||||
`,
|
|
||||||
'src/style-paths/variables.less': '@primary-color: #ADDADD;',
|
'src/style-paths/variables.less': '@primary-color: #ADDADD;',
|
||||||
'src/styles.less': `
|
'src/styles.less': `
|
||||||
@import 'variables';
|
@import 'variables';
|
||||||
@ -43,17 +32,14 @@ export default async function () {
|
|||||||
await replaceInFile(
|
await replaceInFile(
|
||||||
'src/app/app.component.ts',
|
'src/app/app.component.ts',
|
||||||
`'./app.component.css\'`,
|
`'./app.component.css\'`,
|
||||||
`'./app.component.scss'` + (esbuild ? '' : `, './app.component.styl', './app.component.less'`),
|
`'./app.component.scss'` + (esbuild ? '' : `, './app.component.less'`),
|
||||||
);
|
);
|
||||||
|
|
||||||
await updateJsonFile('angular.json', (workspaceJson) => {
|
await updateJsonFile('angular.json', (workspaceJson) => {
|
||||||
const appArchitect = workspaceJson.projects['test-project'].architect;
|
const appArchitect = workspaceJson.projects['test-project'].architect;
|
||||||
appArchitect.build.options.styles = [{ input: 'src/styles.scss' }];
|
appArchitect.build.options.styles = [{ input: 'src/styles.scss' }];
|
||||||
if (!esbuild) {
|
if (!esbuild) {
|
||||||
appArchitect.build.options.styles.push(
|
appArchitect.build.options.styles.push({ input: 'src/styles.less' });
|
||||||
{ input: 'src/styles.styl' },
|
|
||||||
{ input: 'src/styles.less' },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
appArchitect.build.options.stylePreprocessorOptions = {
|
appArchitect.build.options.stylePreprocessorOptions = {
|
||||||
includePaths: ['src/style-paths'],
|
includePaths: ['src/style-paths'],
|
||||||
@ -64,9 +50,7 @@ export default async function () {
|
|||||||
await expectFileToMatch('dist/test-project/styles.css', /h1\s*{\s*color: red;\s*}/);
|
await expectFileToMatch('dist/test-project/styles.css', /h1\s*{\s*color: red;\s*}/);
|
||||||
await expectFileToMatch('dist/test-project/main.js', /h2.*{.*color: red;.*}/);
|
await expectFileToMatch('dist/test-project/main.js', /h2.*{.*color: red;.*}/);
|
||||||
if (!esbuild) {
|
if (!esbuild) {
|
||||||
// These checks are for the less and stylus files
|
// These checks are for the less files
|
||||||
await expectFileToMatch('dist/test-project/styles.css', /h3\s*{\s*color: #008000;\s*}/);
|
|
||||||
await expectFileToMatch('dist/test-project/main.js', /h4.*{.*color: #008000;.*}/);
|
|
||||||
await expectFileToMatch('dist/test-project/styles.css', /h5\s*{\s*color: #ADDADD;\s*}/);
|
await expectFileToMatch('dist/test-project/styles.css', /h5\s*{\s*color: #ADDADD;\s*}/);
|
||||||
await expectFileToMatch('dist/test-project/main.js', /h6.*{.*color: #ADDADD;.*}/);
|
await expectFileToMatch('dist/test-project/main.js', /h6.*{.*color: #ADDADD;.*}/);
|
||||||
}
|
}
|
||||||
@ -77,8 +61,6 @@ export default async function () {
|
|||||||
|
|
||||||
await expectFileToMatch('dist/test-project/styles.css', /h1\s*{\s*color: red;\s*}/);
|
await expectFileToMatch('dist/test-project/styles.css', /h1\s*{\s*color: red;\s*}/);
|
||||||
await expectFileToMatch('dist/test-project/main.js', /h2.*{.*color: red;.*}/);
|
await expectFileToMatch('dist/test-project/main.js', /h2.*{.*color: red;.*}/);
|
||||||
await expectFileToMatch('dist/test-project/styles.css', /h3\s*{\s*color: #008000;\s*}/);
|
|
||||||
await expectFileToMatch('dist/test-project/main.js', /h4.*{.*color: #008000;.*}/);
|
|
||||||
await expectFileToMatch('dist/test-project/styles.css', /h5\s*{\s*color: #ADDADD;\s*}/);
|
await expectFileToMatch('dist/test-project/styles.css', /h5\s*{\s*color: #ADDADD;\s*}/);
|
||||||
await expectFileToMatch('dist/test-project/main.js', /h6.*{.*color: #ADDADD;.*}/);
|
await expectFileToMatch('dist/test-project/main.js', /h6.*{.*color: #ADDADD;.*}/);
|
||||||
}
|
}
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
import {
|
|
||||||
writeMultipleFiles,
|
|
||||||
deleteFile,
|
|
||||||
expectFileToMatch,
|
|
||||||
replaceInFile,
|
|
||||||
} from '../../../utils/fs';
|
|
||||||
import { expectToFail } from '../../../utils/utils';
|
|
||||||
import { ng } from '../../../utils/process';
|
|
||||||
import { updateJsonFile } from '../../../utils/project';
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
// TODO(architect): Delete this test. It is now in devkit/build-angular.
|
|
||||||
|
|
||||||
return writeMultipleFiles({
|
|
||||||
'src/styles.styl': `
|
|
||||||
@import './imported-styles.styl';
|
|
||||||
body { background-color: blue; }
|
|
||||||
`,
|
|
||||||
'src/imported-styles.styl': 'p { background-color: red; }',
|
|
||||||
'src/app/app.component.styl': `
|
|
||||||
.outer {
|
|
||||||
.inner {
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.then(() => deleteFile('src/app/app.component.css'))
|
|
||||||
.then(() =>
|
|
||||||
updateJsonFile('angular.json', (workspaceJson) => {
|
|
||||||
const appArchitect = workspaceJson.projects['test-project'].architect;
|
|
||||||
appArchitect.build.options.styles = [{ input: 'src/styles.styl' }];
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.then(() =>
|
|
||||||
replaceInFile('src/app/app.component.ts', './app.component.css', './app.component.styl'),
|
|
||||||
)
|
|
||||||
.then(() => ng('build', '--source-map', '--configuration=development'))
|
|
||||||
.then(() =>
|
|
||||||
expectFileToMatch('dist/test-project/styles.css', /body\s*{\s*background-color: #00f;\s*}/),
|
|
||||||
)
|
|
||||||
.then(() =>
|
|
||||||
expectFileToMatch('dist/test-project/styles.css', /p\s*{\s*background-color: #f00;\s*}/),
|
|
||||||
)
|
|
||||||
.then(() =>
|
|
||||||
expectToFail(() => expectFileToMatch('dist/test-project/styles.css', '"mappings":""')),
|
|
||||||
)
|
|
||||||
.then(() =>
|
|
||||||
expectFileToMatch('dist/test-project/main.js', /.outer.*.inner.*background:\s*#[fF]+/),
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user