diff --git a/__tests__/test.util.ts b/__tests__/test.util.ts index 281e2da..dc353f0 100644 --- a/__tests__/test.util.ts +++ b/__tests__/test.util.ts @@ -1,11 +1,9 @@ import {minifyCSS} from "../src/helpers/css.util"; - -const cleanCSS = require("clean-css"); const glob = require("glob"); const path = require('path'); const fs = require('fs'); const postcss = require('postcss'); -const sass = require('postcss-node-sass'); +const sass = require('@datorama/postcss-node-sass'); import {ProcessOptions} from "postcss"; import palette from './palettes/palette'; diff --git a/dist/helpers/css.util.d.ts b/dist/helpers/css.util.d.ts new file mode 100644 index 0000000..e687ded --- /dev/null +++ b/dist/helpers/css.util.d.ts @@ -0,0 +1 @@ +export declare function minifyCSS(css: any): string; diff --git a/dist/helpers/css.util.js b/dist/helpers/css.util.js new file mode 100644 index 0000000..9864551 --- /dev/null +++ b/dist/helpers/css.util.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var _cleanCSS = require('clean-css'); +var cleanCSS = new _cleanCSS({}); +function minifyCSS(css) { + return cleanCSS.minify(css).styles; +} +exports.minifyCSS = minifyCSS; diff --git a/dist/index.js b/dist/index.js index a7998fa..42e4c7c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -9,13 +9,12 @@ var __assign = (this && this.__assign) || Object.assign || function(t) { }; Object.defineProperty(exports, "__esModule", { value: true }); var json_util_1 = require("./helpers/json.util"); +var css_util_1 = require("./helpers/css.util"); var postcss = require('postcss'); var fs = require('fs-extra'); var hexToRgba = require('hex-to-rgba'); var THEMIFY = 'themify'; var JSToSass = require('./helpers/js-sass'); -var _cleanCSS = require('clean-css'); -var cleanCSS = new _cleanCSS(); var defaultOptions = { createVars: true, palette: {}, @@ -165,6 +164,9 @@ function themify(options) { */ function processRules(root) { root.walkRules(function (rule) { + if (!hasThemify(rule.toString())) { + return; + } var aggragatedSelectorsMap = {}; var aggragatedSelectors = []; var createdRules = []; @@ -180,9 +182,9 @@ function themify(options) { var defaultVariationValue = variationValueMap[defaultVariation]; decl.value = defaultVariationValue; // indicate if we have a global rule, that cannot be nested - var isGlobalRule = rule.parent && rule.parent.type === 'atrule' && /keyframes/.test(rule.parent.name); + var createNonDefaultVariationRules = isAtRule(rule); // don't create extra CSS for global rules - if (isGlobalRule) { + if (createNonDefaultVariationRules) { return; } // create a new declaration and append it to each rule @@ -225,6 +227,14 @@ function themify(options) { var _a; }); } + /** + * indicate if we have a global rule, that cannot be nested + * @param rule + * @return {boolean} + */ + function isAtRule(rule) { + return rule.parent && rule.parent.type === 'atrule'; + } /** * Walk through all rules, and generate a CSS fallback for legacy browsers. * Two files shall be created for full compatibility: @@ -243,7 +253,56 @@ function themify(options) { variationValues.forEach(function (variation) { return (output["DYNAMIC_EXPRESSION" /* DYNAMIC_EXPRESSION */][variation] = []); }); // define which modes need to be processed var execModes = ["CSS_COLOR" /* CSS_COLOR */, "DYNAMIC_EXPRESSION" /* DYNAMIC_EXPRESSION */]; + walkFallbackAtRules(root, execModes, output); + walkFallbackRules(root, execModes, output); + writeFallbackCSS(output); + var _a; + } + function writeFallbackCSS(output) { + // write the CSS & JSON to external files + if (output["CSS_COLOR" /* CSS_COLOR */].length) { + // write CSS fallback; + var fallbackCss = output["CSS_COLOR" /* CSS_COLOR */].join(''); + writeToFile(options.fallback.cssPath, css_util_1.minifyCSS(fallbackCss)); + // creating a JSON for the dynamic expressions + var jsonOutput_1 = {}; + variationValues.forEach(function (variationName) { + jsonOutput_1[variationName] = output["DYNAMIC_EXPRESSION" /* DYNAMIC_EXPRESSION */][variationName] || []; + jsonOutput_1[variationName] = json_util_1.minifyJSON(jsonOutput_1[variationName].join('')); + // minify the CSS output + jsonOutput_1[variationName] = css_util_1.minifyCSS(jsonOutput_1[variationName]); + }); + // stringify and save + var dynamicCss = JSON.stringify(jsonOutput_1); + writeToFile(options.fallback.dynamicPath, dynamicCss); + } + } + function walkFallbackAtRules(root, execModes, output) { + root.walkAtRules(function (atRule) { + if (atRule.nodes && hasThemify(atRule.toString())) { + execModes.forEach(function (mode) { + var clonedAtRule = atRule.clone(); + clonedAtRule.nodes.forEach(function (rule) { + rule.walkDecls(function (decl) { + var propertyValue = decl.value; + // replace the themify token, if exists + if (hasThemify(propertyValue)) { + var colorMap = getThemifyValue(propertyValue, mode); + decl.value = colorMap[defaultVariation]; + } + }); + }); + var rulesOutput = mode === "DYNAMIC_EXPRESSION" /* DYNAMIC_EXPRESSION */ ? output[mode][defaultVariation] : output[mode]; + rulesOutput.push(clonedAtRule); + }); + } + }); + } + function walkFallbackRules(root, execModes, output) { root.walkRules(function (rule) { + if (isAtRule(rule) || !hasThemify(rule.toString())) { + return; + } var ruleModeMap = {}; rule.walkDecls(function (decl) { var propertyValue = decl.value; @@ -251,6 +310,7 @@ function themify(options) { return; var property = decl.prop; execModes.forEach(function (mode) { + var colorMap = getThemifyValue(propertyValue, mode); // lazily creating a new rule for each variation, for the specific mode if (!ruleModeMap.hasOwnProperty(mode)) { ruleModeMap[mode] = {}; @@ -264,15 +324,11 @@ function themify(options) { } // push the new rule into the right place, // so we can write them later to external file - var rulesOutput = output[mode]; - if (!Array.isArray(rulesOutput)) { - rulesOutput = rulesOutput[variationName]; - } + var rulesOutput = mode === "DYNAMIC_EXPRESSION" /* DYNAMIC_EXPRESSION */ ? output[mode][variationName] : output[mode]; rulesOutput.push(newRule); ruleModeMap[mode][variationName] = newRule; }); } - var colorMap = getThemifyValue(propertyValue, mode); // create and append a new declaration variationValues.forEach(function (variationName) { var underlineColor = colorMap[variationName]; @@ -284,24 +340,6 @@ function themify(options) { }); }); }); - // write the CSS & JSON to external files - if (output["CSS_COLOR" /* CSS_COLOR */].length) { - // write CSS fallback; - var fallbackCss = output["CSS_COLOR" /* CSS_COLOR */].join(''); - writeToFile(options.fallback.cssPath, fallbackCss); - // creating a JSON for the dynamic expressions - var jsonOutput_1 = {}; - variationValues.forEach(function (variationName) { - jsonOutput_1[variationName] = output["DYNAMIC_EXPRESSION" /* DYNAMIC_EXPRESSION */][variationName] || []; - jsonOutput_1[variationName] = json_util_1.minifyJSON(jsonOutput_1[variationName].join('')); - // minify the CSS output - jsonOutput_1[variationName] = cleanCSS.minify(jsonOutput_1[variationName]).styles; - }); - // stringify and save - var dynamicCss = JSON.stringify(jsonOutput_1); - writeToFile(options.fallback.dynamicPath, dynamicCss); - } - var _a; } function createDecl(prop, value) { return postcss.decl({ prop: prop, value: value }); @@ -335,8 +373,8 @@ function themify(options) { }) .join(','); } - function cloneEmptyRule(rule) { - var clonedRule = rule.clone(); + function cloneEmptyRule(rule, overrideConfig) { + var clonedRule = rule.clone(overrideConfig); // remove all the declaration from this rule clonedRule.removeAll(); return clonedRule; diff --git a/dist/package.json b/dist/package.json index 04ad258..f015f82 100644 --- a/dist/package.json +++ b/dist/package.json @@ -1,27 +1,28 @@ { "name": "@datorama/themify", - "version": "0.2.0-beta", - "description": "CSS themes made easy", + "version": "0.0.0-development", + "description": "CSS themes made easy. A robust, opinionated solution to manage themes in your web application", "main": "index.js", "gh-pages-deploy": { "staticpath": "playground", "commit": "pages" }, "scripts": { + "setup": "semantic-release-cli setup", "github-pages": "gh-pages-deploy", "contributors:add": "all-contributors add", "contributors:generate": "all-contributors generate", - "play": "cross-env NODE_ENV=test gulp --gulpfile ./playground/gulpfile.js", + "play": "gulp --gulpfile ./playground/gulpfile.js", "commit": "git-cz", - "build": "npm run sass:support && npm run clean:dist && tsc && npm run copy:dist", + "build": "npm run clean:dist && tsc && npm run copy:dist", "copy:dist": "cp -R src/sass/. package.json dist", "clean:dist": "rimraf dist", "format": "prettier --write --config .prettierrc src/*.ts src/**/*.ts playground/*.js", - "test": "cross-env NODE_ENV=test npm run sass:support && jest", + "test": "jest", "commitmsg": "commitlint -e $GIT_PARAMS", "precommit": "lint-staged", - "sass:support": "node replace.js", - "ts": "gulp --gulpfile playground/gulpfile.js ts" + "travis-deploy-once": "travis-deploy-once", + "semantic-release": "semantic-release" }, "jest": { "moduleFileExtensions": [ @@ -56,9 +57,15 @@ "path": "./node_modules/cz-conventional-changelog" } }, + "dependencies": { + "@datorama/postcss-node-sass": "^1.0.0" + }, "devDependencies": { "@commitlint/cli": "^6.1.3", "@commitlint/config-angular": "^6.1.3", + "@semantic-release/changelog": "^2.0.1", + "@semantic-release/git": "^4.0.1", + "@semantic-release/npm": "^3.2.2", "@types/jest": "^22.2.0", "@types/node": "^9.4.6", "all-contributors-cli": "^4.11.1", @@ -79,12 +86,38 @@ "lint-staged": "^7.0.0", "node-sass": "^4.8.3", "postcss": "^6.0.19", - "postcss-node-sass": "2.1.4", "prettier": "^1.11.1", - "replace-in-file": "^3.4.0", "rimraf": "^2.6.2", + "semantic-release": "^15.3.1", + "semantic-release-cli": "^4.0.1", "tmp": "0.0.33", + "travis-deploy-once": "^5.0.0", "ts-jest": "^22.4.1", "typescript": "^2.7.2" + }, + "release": { + "verifyConditions": [ + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/git" + ], + "prepare": [ + "@semantic-release/changelog", + { + "path": "@semantic-release/npm", + "pkgRoot": "dist" + }, + "@semantic-release/git" + ], + "publish": [ + { + "path": "@semantic-release/npm", + "pkgRoot": "dist" + } + ] + }, + "repository": { + "type": "git", + "url": "https://github.com/datorama/themify.git" } } diff --git a/dist/rule-processor.d.ts b/dist/rule-processor.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/dist/rule-processor.js b/dist/rule-processor.js new file mode 100644 index 0000000..3918c74 --- /dev/null +++ b/dist/rule-processor.js @@ -0,0 +1 @@ +"use strict"; diff --git a/package.json b/package.json index 12f4842..0a18e79 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,15 @@ "github-pages": "gh-pages-deploy", "contributors:add": "all-contributors add", "contributors:generate": "all-contributors generate", - "play": "cross-env NODE_ENV=test gulp --gulpfile ./playground/gulpfile.js", + "play": "gulp --gulpfile ./playground/gulpfile.js", "commit": "git-cz", - "build": "npm run sass:support && npm run clean:dist && tsc && npm run copy:dist", + "build": "npm run clean:dist && tsc && npm run copy:dist", "copy:dist": "cp -R src/sass/. package.json dist", "clean:dist": "rimraf dist", "format": "prettier --write --config .prettierrc src/*.ts src/**/*.ts playground/*.js", - "test": "cross-env NODE_ENV=test npm run sass:support && jest", + "test": "jest", "commitmsg": "commitlint -e $GIT_PARAMS", "precommit": "lint-staged", - "sass:support": "node replace.js", "travis-deploy-once": "travis-deploy-once", "semantic-release": "semantic-release" }, @@ -61,6 +60,10 @@ "devDependencies": { "@commitlint/cli": "^6.1.3", "@commitlint/config-angular": "^6.1.3", + "@datorama/postcss-node-sass": "^1.0.0", + "@semantic-release/changelog": "^2.0.1", + "@semantic-release/git": "^4.0.1", + "@semantic-release/npm": "^3.2.2", "@types/jest": "^22.2.0", "@types/node": "^9.4.6", "all-contributors-cli": "^4.11.1", @@ -81,19 +84,14 @@ "lint-staged": "^7.0.0", "node-sass": "^4.8.3", "postcss": "^6.0.19", - "postcss-node-sass": "2.1.4", "prettier": "^1.11.1", - "replace-in-file": "^3.4.0", "rimraf": "^2.6.2", "semantic-release": "^15.3.1", "semantic-release-cli": "^4.0.1", "tmp": "0.0.33", + "travis-deploy-once": "^5.0.0", "ts-jest": "^22.4.1", - "typescript": "^2.7.2", - "@semantic-release/changelog": "^2.0.1", - "@semantic-release/git": "^4.0.1", - "@semantic-release/npm": "^3.2.2", - "travis-deploy-once": "^5.0.0" + "typescript": "^2.7.2" }, "release": { "verifyConditions": [ diff --git a/playground/gulpfile.js b/playground/gulpfile.js index f827101..034281c 100644 --- a/playground/gulpfile.js +++ b/playground/gulpfile.js @@ -1,5 +1,5 @@ const rename = require('gulp-rename'); -const sass = require('postcss-node-sass'); +const sass = require('@datorama/postcss-node-sass'); const postcss = require('gulp-postcss'); const gulp = require('gulp'); const { initThemify, themify } = require('../dist'); diff --git a/replace.js b/replace.js deleted file mode 100644 index fb489c8..0000000 --- a/replace.js +++ /dev/null @@ -1,25 +0,0 @@ -/** Remove this 💩 when postcss-node-sass will upgrade the node-sass version */ -const replace = require('replace-in-file'); - -const options = { - files: 'src/sass/encode/encode/api/_json.scss', - from : `@return call(get-function('_json-encode--#{$type}'), $value);`, - to : `@return call('_json-encode--#{$type}', $value);`, -}; - -const optionsTwo = { - files: 'src/sass/encode/encode/api/_json.scss', - from : `@return call('_json-encode--#{$type}', $value);`, - to : `@return call(get-function('_json-encode--#{$type}'), $value);`, -}; - -try { - if( process.env.NODE_ENV === 'test' ) { - replace.sync(options); - } else { - replace.sync(optionsTwo); - } -} -catch( error ) { - console.error('Error occurred:', error); -} \ No newline at end of file diff --git a/src/sass/encode/encode/api/_json.scss b/src/sass/encode/encode/api/_json.scss index c4c18aa..002bd40 100644 --- a/src/sass/encode/encode/api/_json.scss +++ b/src/sass/encode/encode/api/_json.scss @@ -14,7 +14,7 @@ $type: type-of($value); @if function-exists('_json-encode--#{$type}') { - @return call('_json-encode--#{$type}', $value); + @return call(get-function('_json-encode--#{$type}'), $value); } @error 'Unknown type for #{$value} (#{$type}).'; diff --git a/yarn.lock b/yarn.lock index bbf75ab..6b02013 100644 --- a/yarn.lock +++ b/yarn.lock @@ -144,6 +144,14 @@ dependencies: find-up "^2.1.0" +"@datorama/postcss-node-sass@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@datorama/postcss-node-sass/-/postcss-node-sass-1.0.0.tgz#511561a2d15fa9b2738c6e001dc4bfda1c823f22" + dependencies: + merge-source-map "^1.0.4" + node-sass "4.9.0" + postcss "^6.0.22" + "@marionebl/sander@^0.6.0": version "0.6.1" resolved "https://registry.yarnpkg.com/@marionebl/sander/-/sander-0.6.1.tgz#1958965874f24bc51be48875feb50d642fc41f7b" @@ -1631,7 +1639,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.3.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^2.1.0: +chalk@^2.1.0, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: @@ -5913,10 +5921,6 @@ nan@^2.10.0, nan@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" -nan@^2.3.2: - version "2.9.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.9.2.tgz#f564d75f5f8f36a6d9456cca7a6c4fe488ab7866" - nanomatch@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" @@ -6045,9 +6049,9 @@ node-pre-gyp@^0.9.0: semver "^5.3.0" tar "^4" -node-sass@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e" +node-sass@4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.0.tgz#d1b8aa855d98ed684d6848db929a20771cc2ae52" dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -6061,7 +6065,7 @@ node-sass@^4.7.2: lodash.mergewith "^4.6.0" meow "^3.7.0" mkdirp "^0.5.1" - nan "^2.3.2" + nan "^2.10.0" node-gyp "^3.3.1" npmlog "^4.0.0" request "~2.79.0" @@ -6976,15 +6980,7 @@ postcss-load-plugins@^2.3.0: cosmiconfig "^2.1.1" object-assign "^4.1.0" -postcss-node-sass@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/postcss-node-sass/-/postcss-node-sass-2.1.4.tgz#8d3eb92297a23356072b277661705972fd0dfab5" - dependencies: - merge-source-map "^1.0.4" - node-sass "^4.7.2" - postcss "^6.0.14" - -postcss@^6.0.0, postcss@^6.0.14: +postcss@^6.0.0: version "6.0.19" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555" dependencies: @@ -7000,6 +6996,14 @@ postcss@^6.0.19: source-map "^0.6.1" supports-color "^5.3.0" +postcss@^6.0.22: + version "6.0.22" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.22.tgz#e23b78314905c3b90cbd61702121e7a78848f2a3" + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + prebuild-install@^2.4.1: version "2.5.3" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.5.3.tgz#9f65f242782d370296353710e9bc843490c19f69" @@ -7499,14 +7503,6 @@ replace-ext@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" -replace-in-file@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/replace-in-file/-/replace-in-file-3.4.0.tgz#b48c94567bbf4f44a2bc6fabdf21ab443e806851" - dependencies: - chalk "^2.3.2" - glob "^7.1.2" - yargs "^11.0.0" - request-debug@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/request-debug/-/request-debug-0.2.0.tgz#fc054ec817181b04ca41a052c136f61c48abaf78" @@ -8624,6 +8620,12 @@ supports-color@^5.2.0, supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + symbol-observable@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"