diff --git a/build/vendors-sass.js b/build/vendors-sass.js new file mode 100644 index 000000000..1d5cc3690 --- /dev/null +++ b/build/vendors-sass.js @@ -0,0 +1,126 @@ +#!/usr/bin/env node + +'use strict' + +const autoprefixer = require('autoprefixer'); +const chalk = require('chalk') +const fs = require('fs') +const glob = require('glob') +const mkdirp = require('mkdirp') +const path = require('path') +const postcss = require('postcss'); +const sass = require('node-sass') +const sh = require('shelljs') + +const basename = path.basename +const dirname = path.dirname +const resolve = path.resolve +const normalize = path.normalize +const join = path.join +const relative = path.relative +const extension = path.extname + +const vendors = () => { + const cwd = 'src/scss/vendors/' + const pattern = '**/*.scss' + const ignore = '**/_*.scss' + const options = { + cwd: cwd, + ignore: ignore + } + const filenames = new glob.sync(pattern, options) + return filenames.map((filename) => { + const obj = {} + obj['dir'] = filename.split('/')[0] + obj['path'] = resolve(cwd, filename) + return obj + }) +} + +const compileSass = (options = {}) => { + // set default options + options = Object.assign({ + style: 'expanded' + }, options); + + // render the result + let compiled + try { + compiled = sass.renderSync({ + file: options.src, + outFile: options.dest, + outputStyle: options.style, + precision: 6, + sourceMap: true, + sourceMapContents: true + }) + } catch(e) { + // catch error, the process crashed + const error = ` + file: ${e.file}, + line: ${e.line}, + column: ${e.column}, + message: ${e.message}, + formatted: ${e.formatted} + ` + console.log(chalk.red(error)) + return + } + + if (compiled && compiled.css){ + console.log(chalk.green('Rendering Complete, saving .css file...')) + console.log(chalk.green(`Wrote CSS to ${options.dest}`)) + console.log(chalk.green(`Wrote Source Map to ${options.map}`)) + console.log(`\n`) + + // add prefixes + const prefixed = postcss([ autoprefixer ]).process(compiled.css, { + from: options.src, + to: options.dest + }) + prefixed.then((result) => { + result.warnings().forEach((warning) => { + console.warn(warning.toString()) + }) + // write the result to file + mkdirp(dirname(options.dest), (error) => { + if (error) return cb(error) + // create .css file + fs.writeFile(options.dest,result.css, (error) => { + if (error) return cb(error) + }) + // create .css.map file + fs.writeFile(options.dest,compiled.map, (error) => { + if (error) return cb(error) + }) + console.log(' ' + options.dest + ' built.'); + }) + }) + } +} + +const compile = (vendors) => { + vendors.forEach((vendor) => { + const dest = resolve(__dirname, '..', 'src/vendors', vendor.dir, 'css', path.parse(vendor.path).name) + // Expanded + compileSass({ + src : vendor.path, + dest: dest + '.css', + map: dest + '.css.map' + }); + + // Minified + compileSass({ + src : vendor.path, + dest: dest + '.min.css', + map: dest + '.min.css.map', + style: 'compressed' + }); + }) +} + +const main = () => { + compile(vendors()) +} + +main() diff --git a/build/vendors.js b/build/vendors.js index da1085d03..62089f858 100644 --- a/build/vendors.js +++ b/build/vendors.js @@ -2,105 +2,141 @@ 'use strict' -const fs = require('fs'); -const path = require('path'); -const mkdirp = require('mkdirp'); +const fs = require('fs') +const path = require('path') +const mkdirp = require('mkdirp') const sh = require('shelljs') -const basename = path.basename; -const dirname = path.dirname; -const resolve = path.resolve; -const normalize = path.normalize; -const join = path.join; -const relative = path.relative; -const extension = path.extname; +const basename = path.basename +const dirname = path.dirname +const resolve = path.resolve +const normalize = path.normalize +const join = path.join +const relative = path.relative +const extension = path.extname -const src = 'src/'; -const dest = 'dist/'; +const src = 'src/' +const dest = 'dist/' +const base = path.resolve(__dirname, '..') const walkSync = (dir, filelist = []) => { fs.readdirSync(dir).forEach(file => { filelist = fs.statSync(path.join(dir, file)).isDirectory() - ? walkSync(path.join(dir, file), filelist) - : filelist.concat(path.join(dir, file)); - }); - return filelist; + ? walkSync(path.join(dir, file), filelist) + : filelist.concat(path.join(dir, file)) + }) + return filelist +} + +const vendorName = (path) => { + const nodeModules = Boolean(path.split('/')[0] === 'node_modules') + const subDir = Boolean(path.indexOf('@') >= 0) + let vendor + if (nodeModules) { + if (subDir) { + vendor = `${path.split('/')[1]}/${path.split('/')[2]}` + } else { + vendor = `${path.split('/')[1]}` + } + } + return vendor +} + +function removeDuplicates( arr, prop ) { + let obj = {}; + return Object.keys(arr.reduce((prev, next) => { + if(!obj[next[prop]]) obj[next[prop]] = next; + return obj; + }, obj)).map((i) => obj[i]); } const findVendors = () => { - const vendors = { css: [], js: [], other: [] }; + const vendors = [] + // const assets = [] + // const vendors = { css: [], js: [], other: [] } const filenames = walkSync(src) filenames.forEach((filename) => { if (extension(filename) === '.html') { - const files = fs.readFileSync(filename, 'ascii').toString().split('\n'); + const files = fs.readFileSync(filename, 'ascii').toString().split('\n') - // go through the list of logFileLines + // go through the list of code lines files.forEach((file) => { - // if the current line matches SAVE, it will be stored in the variable lines - if(file.match(/node_modules/)) { - - const js = file.match(/node_modules.*.js/) - if (js !== null) { - // vendors.js.indexOf(resolve(js[0])) === -1 ? vendors.js.push({'html':js[0],'absolute':resolve(js[0]) }) : ''; - vendors.js.map((item) => { return item.html }).indexOf(js[0]) === -1 ? vendors.js.push({'html':js[0],'absolute':resolve(js[0]) }) : ''; - } - const css = file.match(/node_modules.*.css/) - if (css !== null) { - if (vendors.css.map((item) => { return item.html }).indexOf(css[0]) === -1) { - // vendors.css.push(resolve(css[0])) - vendors.css.push({'html':css[0],'absolute':resolve(css[0]) }) - - const assets = fs.readFileSync(css[0], 'ascii').toString().match(/url\(.*?\)/ig); - assets.forEach(function(asset) { - const assetPath = asset.replace(/\?.*/g, '').replace('url(','').replace(/\'/g, '').replace(')',''); - vendors.other.push({'absolute' : resolve(dirname(css[0]), assetPath), 'relative' : assetPath }) - }) + // if the current line matches `/(?:href|src)="(node_modules.*.[css|js])"/`, it will be stored in the variable lines + const nodeModules = file.match(/(?:href|src)="(node_modules.*.[css|js])"/) + if (nodeModules) { + let vendor = [] + const src = nodeModules[1] + const name = vendorName(src) + let type + let absolute + + vendor['name'] = name + vendor['filetype'] = extension(src).replace('.', '') + vendor['src'] = src + vendor['absolute'] = resolve(src) + + if (vendors.findIndex(vendor => vendor.absolute === resolve(src)) === -1) { + vendors.push(vendor) + + // Check it CSS file has assets + if (extension(src) === '.css') { + const assets = fs.readFileSync(resolve(src), 'ascii').toString().match(/(?:url)\((.*?)\)/ig) + if (assets) { + assets.forEach((asset) => { + const assetPath = asset.match(/(?:url)\((.*?)\)/)[1] + let subVendor = [] + if (assetPath !== undefined) { + // console.log(assetPath) + const path = assetPath.replace(/\?.*/, '').replace(/\'|\"/, '') + subVendor['name'] = name + subVendor['filetype'] = 'other' + subVendor['src'] = normalize(`css/${path}`) + subVendor['absolute'] = resolve(dirname(src), path) + + vendors.push(subVendor) + } + }) + } } } } }) } }) - return vendors; + return vendors } const copyFiles = (files, dest) => { files.forEach((file) => { - mkdirp.sync(resolve(dest)); - fs.createReadStream(file).pipe(fs.createWriteStream(resolve(dest, basename(file)))); - }) -} + let dir + file.filetype !== 'other' ? dir = resolve(dest, file.name, file.filetype) : dir = resolve(dest, file.name, dirname(file.src)) + mkdirp.sync(dir) + fs.createReadStream(file.absolute).pipe(fs.createWriteStream(resolve(dir, basename(file.src)))) -const copyOtherFiles = (files, dest) => { - files.forEach((file) => { - mkdirp.sync(resolve(dest + dirname(file.relative))); - fs.createReadStream(file.absolute).pipe(fs.createWriteStream(resolve(dest, file.relative))); + if (fs.existsSync(`${file.absolute}.map`)) { + fs.createReadStream(`${file.absolute}.map`).pipe(fs.createWriteStream(resolve(dir, `${basename(file.src)}.map`))) + } }) } -const replaceRecursively = (filename, original) => { - const replacement = 'vendors/' + extension(original).replace('.','') + '/' + basename(original); +const replaceRecursively = (filename, vendor) => { + const original = vendor.src + const replacement = `vendors/${vendor.name}/${vendor.filetype}/${basename(vendor.src)}` sh.sed('-i', original, replacement, filename) } const main = () => { - const vendors = findVendors() - - copyFiles(vendors.css.map((item) => { return item.absolute }), './dist/vendors/css/'); - copyFiles(vendors.js.map((item) => { return item.absolute }), './dist/vendors/js/'); - copyOtherFiles(vendors.other, './dist/vendors/css/'); - + copyFiles(vendors.map((file) => { return file }), './dist/vendors/') const filenames = walkSync(dest) filenames.forEach((filename) => { if (extension(filename) === '.html') { - vendors.css.map((item) => { - replaceRecursively(resolve(filename), item.html) - }) - vendors.js.map((item) => { - replaceRecursively(resolve(filename), item.html) + vendors.map((vendor) => { + if (vendor.filetype !== 'other') { + replaceRecursively(resolve(filename), vendor) + } }) } }) diff --git a/package-lock.json b/package-lock.json index f206c30df..b71b7d245 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@coreui/coreui-free-bootstrap-admin-template", - "version": "2.0.0-rc.0", + "version": "2.0.0-rc.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -110,7 +110,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -298,7 +298,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -398,7 +398,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -501,7 +501,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -680,7 +680,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -823,7 +823,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -946,7 +946,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -1026,7 +1026,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -1140,7 +1140,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -1262,7 +1262,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -1322,7 +1322,7 @@ "integrity": "sha512-X3Ur/A/lIbbP8W0pmwgqtDXIxhQmxPaiwY9SKP7kF9wvZfjZRwMvbJE92ozUhF3UDK3DCKaV7oGqmI1rP/zqWA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -1495,7 +1495,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -1633,7 +1633,7 @@ "integrity": "sha512-r4snW6Q8ICL3Y8hGzYJRvyG/+sc+kvkewXNedG9tQjoHmUFMwMSv/o45GWQUQswevGnWghiGkpRPivFfOuMsOA==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -2555,7 +2555,7 @@ "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "esutils": "2.0.2", "js-tokens": "3.0.2" } @@ -2761,7 +2761,7 @@ "requires": { "ansi-align": "2.0.0", "camelcase": "4.1.0", - "chalk": "2.3.1", + "chalk": "2.4.1", "cli-boxes": "1.0.0", "string-width": "2.1.1", "term-size": "1.2.0", @@ -3015,9 +3015,9 @@ "dev": true }, "chalk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { "ansi-styles": "3.2.1", @@ -4115,7 +4115,7 @@ "requires": { "ajv": "5.5.2", "babel-code-frame": "6.26.0", - "chalk": "2.3.1", + "chalk": "2.4.1", "concat-stream": "1.6.2", "cross-spawn": "5.1.0", "debug": "3.1.0", @@ -4179,7 +4179,7 @@ "requires": { "ajv": "5.5.2", "ajv-keywords": "2.1.1", - "chalk": "2.3.1", + "chalk": "2.4.1", "lodash": "4.17.5", "slice-ansi": "1.0.0", "string-width": "2.1.1" @@ -6693,7 +6693,7 @@ "dev": true, "requires": { "ansi-escapes": "3.1.0", - "chalk": "2.3.1", + "chalk": "2.4.1", "cli-cursor": "2.1.0", "cli-width": "2.2.0", "external-editor": "2.2.0", @@ -7545,7 +7545,7 @@ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, "requires": { - "chalk": "2.3.1" + "chalk": "2.4.1" } }, "log-update": { @@ -8460,7 +8460,7 @@ "dev": true, "requires": { "ansi-styles": "3.2.1", - "chalk": "2.3.1", + "chalk": "2.4.1", "cross-spawn": "5.1.0", "memorystream": "0.3.1", "minimatch": "3.0.4", @@ -9066,7 +9066,7 @@ "integrity": "sha512-f13HRz0HtVwVaEuW6J6cOUCBLFtymhgyLPV7t4QEk2UD3twRI9IluDcQNdzQdBpiixkXj2OmzejhhTbSbDxNTg==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "source-map": "0.6.1", "supports-color": "5.3.0" }, @@ -9085,7 +9085,7 @@ "integrity": "sha512-LbSZQUu1fh7hiIU/JCitSWd+V3MO60DWi9ETUKiO7i9fDZN/9XqI3ACbAOnymd9a+8v5x5XI5SjeEv4/R+l/Ow==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "chokidar": "2.0.3", "dependency-graph": "0.7.0", "fs-extra": "5.0.0", @@ -9715,7 +9715,7 @@ "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", "dev": true, "requires": { - "chalk": "2.3.1", + "chalk": "2.4.1", "lodash": "4.17.5", "log-symbols": "2.2.0", "postcss": "6.0.19" @@ -11325,7 +11325,7 @@ "requires": { "autoprefixer": "8.4.1", "balanced-match": "1.0.0", - "chalk": "2.3.1", + "chalk": "2.4.1", "cosmiconfig": "4.0.0", "debug": "3.1.0", "execall": "1.0.0", @@ -11643,7 +11643,7 @@ "requires": { "ajv": "6.4.0", "ajv-keywords": "3.1.0", - "chalk": "2.3.1", + "chalk": "2.4.1", "lodash": "4.17.5", "slice-ansi": "1.0.0", "string-width": "2.1.1" @@ -12177,7 +12177,7 @@ "dev": true, "requires": { "boxen": "1.3.0", - "chalk": "2.3.1", + "chalk": "2.4.1", "configstore": "3.1.2", "import-lazy": "2.1.0", "is-ci": "1.1.0", diff --git a/package.json b/package.json index 5d71a1083..9d7b5e2f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@coreui/coreui-free-bootstrap-admin-template", - "version": "2.0.0-rc.0", + "version": "2.0.0-rc.1", "description": "Free Bootstrap Admin Template", "keywords": [ "admin", @@ -46,12 +46,10 @@ "build-vendors": "node build/vendors.js", "css": "npm-run-all --parallel css-compile* --sequential css-prefix css-minify*", "css-compile": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 src/scss/style.scss src/css/style.css", - "css-compile-vendors": "foreach -g \"src/scss/vendors/**/*.scss\" -i \"src/scss/vendors/**/_*.scss\" -x \"node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 --output src/vendors/css/ #{path}\" --no-c", + "css-compile-vendors": "node build/vendors-sass.js", "css-lint": "stylelint --config build/.stylelintrc --syntax scss \"src/scss/**/*.scss\"", "css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output src/css/style.min.css src/css/style.css", - "css-minify-vendors": "foreach -g \"src/vendors/css/*.css\" -i \"src/vendors/css/*.min.css\" -x \"cleancss --level 1 --source-map --source-map-inline-sources #{path} --output #{dir}/#{name}.min#{ext}\" --no-c", "css-prefix": "postcss --config build/postcss.config.js --replace \"src/css/*.css\" \"!src/css/*.min.css\"", - "css-prefix-vendors": "postcss --config build/postcss.config.js --replace \"src/vendors/css/**/*.css\" \"!src/vendors/css/**/*.css\"", "js": "npm-run-all --parallel js-compile* js-lint*", "js-compile": "cross-env PLUGINS=true babel src/js/src/ --out-dir src/js/ --source-maps", "js-lint": "eslint src/js/src", @@ -84,6 +82,7 @@ "babel-eslint": "^8.2.3", "babel-plugin-transform-es2015-modules-strip": "^0.1.1", "browser-sync": "2.24.1", + "chalk": "^2.4.1", "clean-css-cli": "^4.1.11", "copyfiles": "^2.0.0", "cross-env": "^5.1.4", diff --git a/src/404.html b/src/404.html index b0d99cd94..d5e5c2538 100644 --- a/src/404.html +++ b/src/404.html @@ -1,7 +1,7 @@ - +
diff --git a/src/500.html b/src/500.html index 6ad6e858c..6a7c16c69 100644 --- a/src/500.html +++ b/src/500.html @@ -1,7 +1,7 @@ - +
diff --git a/src/base-breadcrumb.html b/src/base-breadcrumb.html index 3f6bdec96..d7fb60f5b 100644 --- a/src/base-breadcrumb.html +++ b/src/base-breadcrumb.html @@ -1,7 +1,7 @@ - +