UNPKG

@visual-framework/vf-core

Version:

Common dependencies for the Visual Framework.

275 lines (236 loc) 9.86 kB
import fastglob from "fast-glob"; import sass from "sass"; import autoprefixer from "gulp-autoprefixer"; import recursive from "../css-generator/recursive-readdir.mjs"; import source from "vinyl-source-stream"; import fs from "fs"; import chalk from "chalk"; import gulpStylelint from "gulp-stylelint"; import rename from "gulp-rename"; import _toesmTemp1 from "stream"; "use strict"; /** * Expose vf-css gulp tasks as a JS module * This makes dependency management a bit cleaner */ export default function(gulp, path, componentPath, componentDirectories, buildDestionation) { // Sass and CSS Stuff const autoprefixerOptions = { overrideBrowserslist: ["last 2 versions", "> 5%", "Firefox ESR"] }; // Build stuff // Linting things const SassInput = componentPath + "/vf-componenet-rollup/index.scss"; const SassOutput = buildDestionation + "/css"; // CSS Gen stuff // construct sass import paths var sassPaths = fastglob.sync([componentPath,componentPath+"/**","!"+componentPath+"/**/*.*"],{onlyFiles: false}); // Lookup each component's package.json and make a package.scss gulp.task("vf-css:package-info", function(done) { const Transform = _toesmTemp1.Transform; // Convert part of the package.json to a sass map function packageJsonToScss(location) { return new Transform({ objectMode: true, transform: (data, _, done) => { location = "components/" + location.split(/-components\/(.+)/)[1]; let name = JSON.parse(data.contents.toString()).name; let version = JSON.parse(data.contents.toString()).version; var output = `$componentInfo: ( name: "` + name + `", version: "` + version + `", location: "` + location + `", vfCoreVersion: "` + global.vfVersion + `", buildTimeStamp: "` + new Date().toUTCString() + `" );`; done(null, output); } }); } recursive(componentPath, ["*.css", "*.scss", "*.md", "*.njk", "_package.json"], function (err, files) { // filter components where no package.json is found files.forEach(function(file, index) { if ((file.file.indexOf("package.json") < 0)) { delete files[index]; } }); var counter = 0; // generate the component package.variables.scss files.forEach(function(file, index, array) { gulp.src(file.dir+"/package.json") .pipe(packageJsonToScss(file.dir)) .pipe(source(file.file_path)) .pipe(rename("package.variables.scss")) .pipe(gulp.dest(file.dir)) .on("end", function() { counter++; // as we have empty items, we need to count and not use index if (counter == Object.keys(array).length) { done(); } }); }); }); }); gulp.task("vf-css:build", function(done) { // console.log(chalk.yellow('Visual Framework Sass generation is being done by:')); // console.log(chalk.yellow(sass.info)); // console.log(chalk.yellow('Looking in these locations for components:')); // console.log(sassPaths); // Import sass files // We'll check to see if the file exists before passing // it to sass for compilation const sassImporter = [function(url,prev,done) { // windows compatibility url = url.replace(/\\/g, "/"); prev = prev.replace(/\\/g, "/"); function truncateFilePath(path) { let pathArray = path.split(/[/]+/); pathArray.shift(); return pathArray.join("/"); } var parentFile = prev.split(/[/]+/).pop(); var underscoredFile = url.split(/[/]+/)[0]+"/_"+url.split(/[/]+/).pop(); // for mixins/vf-utility-mixins.scss -> mixins/_vf-utility-mixins.scss var truncatedFile = truncateFilePath(url); // last resort matching, mostly for mixins var underscoredTrucncatedFile = truncatedFile.split(/[/]+/)[0]+"/_"+truncatedFile.split(/[/]+/).pop(); // for mixins/vf-utility-mixins.scss -> mixins/_vf-utility-mixins.scss // If you do not want to interveen in certain file names // if (parentFile == '_index.scss' || parentFile == '_vf-mixins.scss' || parentFile == 'vf-functions.scss') { // return null; // } // only intervene in index.scss rollups // ignore `package.variables.scss` as it is dynamically made and gulp doesn't see it quickly enough if (parentFile == "index.scss" && url != "package.variables.scss") { if (availableComponents[url]) { done({file: url}); } else if (availableComponents[underscoredFile]) { // maybe it was an _filename.scss? done({file: underscoredFile}); } else if (availableComponents[truncatedFile]) { done({file: truncatedFile}); } else if (availableComponents[underscoredTrucncatedFile]) { done({file: underscoredTrucncatedFile}); } else { let importWarning = "Notice: Couldn't find ${url} referenced in ${prev}, the CSS won't be included in the build. If this is expected, you might want to comment out the dependency."; console.warn(chalk.yellow(importWarning)); done({ contents: `/* ${importWarning} */` }); } } else { return null; } }]; // Find all the component sass files available. // so we only include the file if it exists. var availableComponents = {}; var sassFileList = fastglob.sync([componentPath+"/**/*.scss",componentPath+"/**/**/*.scss"], { ignore: [componentPath+"/vf-core-components/vf-core/components/**/*.scss"] } ); // Keep only the directory + file name for (let index = 0; index < sassFileList.length; index++) { let value = sassFileList[index]; value = value.replace(/\\/g, "/"); // windows compatibility value = value.split(/[/]+/).slice(-2).join("/"); // make a list of paths like vf-table/vf-table.scss availableComponents[value] = true; } // console.log('These components were found'); // console.log('availableComponents',availableComponents) // generate the css sass.render({ // https://github.com/sass/node-sass file: SassInput, importer: sassImporter, outputStyle: "compressed", sourceMap: true, outFile: SassOutput+"/styles.css", includePaths: sassPaths }, function(err, result) { if (err) { console.log(chalk.yellow(err)); } if (!err){ fs.mkdirSync(SassOutput, { recursive: true }); // make folder, if it doesn't exist fs.writeFile(SassOutput+"/styles.css", result.css, function(err){ if(!err){ // console.log('writing',SassOutput+'/styles.css') } else { console.log(chalk.yellow(err)); } }); fs.writeFile(SassOutput+"/styles.css.map", result.map, function(err){ if(!err){ // console.log('writing',SassOutput+'/styles.css.map') } else { console.log(chalk.yellow(err)); } }); } done(); }); }); // Sass Build-Time things // Take the built styles.css and autoprefixer it gulp.task("vf-css:production", function(done) { return gulp .src(SassOutput + "/styles.css") .pipe(autoprefixer(autoprefixerOptions)) .pipe(gulp.dest(SassOutput)) .on("end", function() { done(); }); }); // Sass Lint // For stylelint config rules see .stylelinrc const vfScssLintPaths = [componentPath+"/**/embl-*.scss", componentPath+"/**/vf-*.scss", "!"+componentPath+"/**/index.scss", "!assets/**/*.scss", "!"+componentPath+"/vf-design-tokens/dist/**/*.scss"]; gulp.task("vf-lint:scss-soft-fail", function() { return gulp .src(vfScssLintPaths) .pipe(gulpStylelint({ failAfterError: false, reporters: [{formatter: "string", console: false}] })); }); gulp.task("vf-lint:scss-hard-fail", function() { return gulp .src(vfScssLintPaths) .pipe(gulpStylelint({ failAfterError: true, reporters: [{formatter: "string", console: true}] })); }); // ----------------------------------------------------------------------------- // CSS Generator Tasks // Generate per-component .css files // ----------------------------------------------------------------------------- var genCss = function (option) { var file_name = path.basename(path.dirname(option.file_path)) + ".css"; sass.render({ file: option.file_path, includePaths: sassPaths, outputStyle: "expanded" }, function(err, result) { if (err) { console.log(chalk.yellow(err)); } if (!err){ fs.mkdirSync(option.dir, { recursive: true }); // make folder, if it doesn't exist fs.writeFile(option.dir+"/"+file_name, result.css, function(err) { if (err) { console.log(chalk.yellow(err)); } else { //prefix // @todo, using gulp one file at a time is weird, but autoprefixer doesn't seem to support passing single values well gulp.src(option.dir+"/"+file_name) .pipe(autoprefixer(autoprefixerOptions)) .pipe(gulp.dest(option.dir)); } }); } return; }); }; gulp.task("vf-css:generate-component-css", function(done) { recursive(componentPath, ["*.css"], function (err, files) { files.forEach(function(file) { // only generate CSS for index.scss files, but not for the vf rollup if ((file.file.indexOf("index.scss") > -1) && (file.file_path.replace(/\\/g, "/").indexOf("vf-componenet-rollup/index.scss") == -1)) { genCss(file); } }); }); done(); }); gulp.task("vf-css", gulp.series( "vf-css:package-info", "vf-css:build" )); return gulp; };