我需要编写一个具有不同“味道”或颜色变量的html5模板。
我想使用一个scss文件,但是要渲染多个css文件。
让我们说我的scss入口点是app.scss
恕我直言,理想的方法是:
$flavors: (
flavor-a: (
background: white
),
flavor-b: (
background: grey
)
);
@mixin flavor($name) {
/* parser-rule-start */
@content;
/* parser-rule-end */
}
html {
/* regular rule - valid for all flavors => goes to app.css */
font-family: sans-serif;
@each $name, $options in $flavors {
@include flavor($name) {
/* flavor-rule => goes to flavor-a.css / flavor-b.css */
background: map-get($options, 'background');
}
}
}
所以我最终还是
我以前有这个要求,并用多个条目文件解决了这个问题,这些文件调用mixins进行着色等等。
但是我不喜欢这种方法,因为在为新组件编码scss之后,我需要将几行代码从结构文件移动到flavor-mixin,这在flavor-*。scss条目文件中称为
我的构建的ATM看起来像(吞咽):
/**
* compile/concat scss
*/
gulp.task('css', function () {
const sassOptions = {
outputStyle: "compressed",
errorLogToConsole: true
};
const autoprefixerOptions = {
browsersList: [
"last 2 versions",
"ie >= 11"
]
};
return gulp
.src("src/scss/*.scss")
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', makeErrorLogger('css')))
.pipe(autoprefixer(autoprefixerOptions))
// .pipe(splitFlavors()) <- the point i would need some magic
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest("public/static/css"))
.pipe(browserSync.stream({match: '**/*.css'}));
});
有人为此目的知道一个gulp插件吗?还是我必须自己编写一个代码?
答案 0 :(得分:0)
更新3
另一种替代品
let newSelector = selector.replace(/\s?\:\:flavor\-([^\s]+)/g, "").trim();
更新2
css规则选择器中的替换需要采用
let newSelector = selector.replace(/\s?\:\:flavor\-([a-zA-Z0-9\-\_\s]+)/g, "").trim();
更新
通过使用修改后的选择器而不是属性,您可以继续在“ for-flavor”块中使用嵌套规则。
因此将mixin调整为:
@mixin for-flavor($name) {
::flavor-#{$name} & {
@content;
}
}
和gulp任务:
const path = require("path");
const gulp = require("gulp");
const sourcemaps = require("gulp-sourcemaps");
const sass = require("gulp-sass");
const autoprefixer = require("gulp-autoprefixer");
const through = require("through2");
const postcss = require("gulp-postcss");
/**
* compile/concat scss
*/
gulp.task('css', function () {
const sassOptions = {
outputStyle: "compressed",
errorLogToConsole: true
};
const autoprefixerOptions = {
browsersList: [
"last 2 versions",
"ie >= 11"
]
};
function addFlavorFiles() {
return through.obj(function(file, encoding, callback) {
/* @var file File */
let content = file.contents.toString();
let names = [];
let matches = content.match(/\:\:flavor\-([^\s\{]+)/g);
if (matches) {
names = matches.map(match => match.replace(/\:\:flavor\-/, '').trim());
// unique
names = names.filter((el, index, arr) => {
return index === arr.indexOf(el);
});
}
names.forEach(name => {
let newFile = file.clone();
newFile.contents = Buffer.concat([Buffer.from(`/*!flavor:${name}*/\n`, encoding), file.contents]);
let filePath = path.parse(file.path);
newFile.path = path.join(filePath.dir, `flavor-${name + filePath.ext}`);
this.push(newFile);
});
callback(null, file);
})
}
function filterFlavors(css, opts) {
let flavor = null;
if (css.nodes[0].type === "comment" && css.nodes[0].text.indexOf('!flavor:') === 0) {
flavor = css.nodes[0].text.replace(/^\!flavor\:/, "").trim();
}
css.walkRules(rule => {
let selector = rule.selector;
if (/^\:\:flavor\-/.test(selector)) {
// flavor rule
if (flavor === null) {
// general file, all flavor rules must go...
rule.remove();
} else {
let matches = selector.match(/\:\:flavor\-([a-zA-Z0-9\-\_]+)/);
let currentFlavor = matches[1];
if (flavor !== currentFlavor) {
// wrong flavor
rule.remove();
} else {
// keep rule but adjust selector
let newSelector = selector.replace(/^\:\:flavor\-([a-zA-Z0-9\-\_]+)/, "").trim();
rule.selector = newSelector;
}
}
} else if(flavor !== null) {
// general rule but flavor file, so remove the rule
rule.remove();
}
});
css.walkRules(rule => {
if (!rule.nodes || rule.nodes.length === 0) {
rule.remove();
}
});
css.walkAtRules(atRule => {
if (!atRule.nodes || atRule.nodes.length === 0) {
atRule.remove();
}
});
// optional: delete all font-face definitions from flavor file
if (flavor !== null) {
css.walkAtRules(atRule => {
if (atRule.name === "font-face") {
atRule.remove();
}
});
}
}
return gulp
.src("src/scss/*.scss")
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', makeErrorLogger('css')))
.pipe(addFlavorFiles())
.pipe(autoprefixer(autoprefixerOptions))
.pipe(postcss([filterFlavors]))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest("public/static/css"))
});
原始帖子
我设法按照自己的意愿解决了
使用Sass混合,添加解析规则:
@mixin for-flavor($name) {
-flavor-start: unquote($name);
@content;
-flavor-end: unquote($name);
}
将其用于CSS声明
// you get the idea...
$flavors: (
"lightblue": (
background: lightblue,
),
"pink": (
background: pink,
),
"dark": (
background: black
),
);
#page-header {
background: black;
@each $name, $options in $flavors {
@if map_has_key($options, 'background') {
@include for-flavor($name) {
background: map_get($options, 'background');
}
}
}
@include for-flavor("lightblue") {
/* special rule for specific flavor */
color: black;
}
}
gulp
const path = require("path");
const gulp = require("gulp");
const sourcemaps = require("gulp-sourcemaps");
const sass = require("gulp-sass");
const autoprefixer = require("gulp-autoprefixer");
const through = require("through2");
const postcss = require("gulp-postcss");
/**
* compile/concat scss
*/
gulp.task('css', function () {
const sassOptions = {
outputStyle: "compressed",
errorLogToConsole: true
};
const autoprefixerOptions = {
browsersList: [
"last 2 versions",
"ie >= 11"
]
};
function addFlavorFiles() {
return through.obj(function(file, encoding, callback) {
/* @var file File */
let content = file.contents.toString();
let names = [];
let matches = content.match(/\-flavor\-start\:([^\;]+)/g);
if (matches) {
names = matches.map(match => match.replace(/\-flavor\-start\:/, '').trim());
}
names.forEach(name => {
let newFile = file.clone();
newFile.contents = Buffer.concat([Buffer.from(`/*!flavor:${name}*/\n`, encoding), file.contents]);
let filePath = path.parse(file.path);
newFile.path = path.join(filePath.dir, `flavor-${name + filePath.ext}`);
this.push(newFile);
});
callback(null, file);
})
}
function filterFlavors(css, opts) {
let flavor = null;
if (css.nodes[0].type === "comment" && css.nodes[0].text.indexOf('!flavor:') === 0) {
flavor = css.nodes[0].text.replace(/^\!flavor\:/, "").trim();
}
let inFlavorBlock = "";
css.walkDecls(decl => {
let prop = decl.prop;
let isControlProp = false;
let value = decl.value.trim();
if (prop === "-flavor-end") {
inFlavorBlock = "";
isControlProp = true;
} else if (prop === "-flavor-start") {
inFlavorBlock = value;
isControlProp = true;
}
let isValid = ((inFlavorBlock === "" && flavor === null) || inFlavorBlock === flavor);
if (isValid === false || isControlProp) {
decl.remove();
}
});
css.walkRules(rule => {
if (!rule.nodes || rule.nodes.length === 0) {
rule.remove();
}
});
css.walkAtRules(atRule => {
if (!atRule.nodes || atRule.nodes.length === 0) {
atRule.remove();
}
});
}
return gulp
.src("src/scss/*.scss")
.pipe(sourcemaps.init())
.pipe(sass(sassOptions))
.pipe(addFlavorFiles())
.pipe(autoprefixer(autoprefixerOptions))
.pipe(postcss([filterFlavors]))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest("public/static/css"))
});
唯一剩下的问题是,源地图没有被过滤...