diff --git a/.gitignore b/.gitignore index 85a164a2..8044e73f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/.sass-cache/ +/**/*.sass-cache/ /export/ /node_modules/ /pattern-library-*.tar.gz diff --git a/.stylelintrc b/.stylelintrc index fbfe5ad5..04fccdce 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -18,6 +18,12 @@ "color-hex-length": "short", "color-no-invalid-hex": true, "comment-empty-line-before": "always", + "declaration-block-no-duplicate-properties": [ + true, + { + "ignore": ["consecutive-duplicates-with-different-values"] + } + ], "csstools/use-logical": "always", "declaration-block-semicolon-newline-after": "always", "declaration-block-semicolon-space-before": "never", diff --git a/Dockerfile b/Dockerfile index 6a6e3de3..93d97c11 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,6 @@ COPY .babelrc \ .stylelintrc \ gulpfile.babel.js \ ./ -COPY libero-config/ libero-config/ COPY --from=npm /app/node_modules/ node_modules/ COPY test/ test/ COPY source/ source/ diff --git a/README.md b/README.md index ed1d29c6..a90fa35c 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,6 @@ Developer quick start: running `docker-compose down --volumes && docker-compose #### Uses of configuration Configuration is used to be the single source of truth for knowledge that needs to be shared across across front end technology boundaries. For example, media query breakpoint values need to exist in the styling layer, but they are also often needed by JavaScript. Note that for flexibility all configuration could be maintained using this system in order to make it easier to later distribute configuration if it suddenly becomes necessary. - -#### Anatomy of configuration -(All config file code examples are taken from `/libero-config/config--libero-default.js`.) ##### Simple example `config.data` is where you define your configuration data. diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 6d508e1a..dff74338 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -7,7 +7,6 @@ services: target: gulp command: bash -c "npx gulp assemble --environment=development --sass-lint=${LINT_SASS} && npx gulp watch --environment=development --sass-lint=${LINT_SASS}" volumes: - - ./libero-config:/app/libero-config - ./source:/app/source watch-build: build: diff --git a/gulpfile.babel.js b/gulpfile.babel.js index c66a5d36..dec408ac 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -1,6 +1,6 @@ import browserSync from 'browser-sync'; import del from 'del'; -import distributeConfig from './libero-config/bin/distributeConfig'; +import distributeConfig from '@libero/pattern-library-config-manager'; import flatten from 'gulp-flatten'; import gulp from 'gulp'; import minimist from 'minimist'; @@ -206,9 +206,10 @@ const watchSass = () => gulp.watch(config.files.src.sass, build); const watchSassTests = () => gulp.watch(config.files.test.sass, build); -const watchSharedConfig = () => gulp.watch('libero-config/**/*', distributeSharedConfig); +// TODO: replace with new watcher once config override arrangement decided +// const watchSharedConfig = () => gulp.watch('libero-config/**/*', distributeSharedConfig); -export const watch = gulp.parallel(watchSass, watchSassTests, watchSharedConfig); +export const watch = gulp.parallel(watchSass, watchSassTests/*, watchSharedConfig */); // Server diff --git a/libero-config/.babelrc b/libero-config/.babelrc deleted file mode 100644 index 0967ef42..00000000 --- a/libero-config/.babelrc +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/libero-config/bin/ConfigGenerator.js b/libero-config/bin/ConfigGenerator.js deleted file mode 100644 index f982d91c..00000000 --- a/libero-config/bin/ConfigGenerator.js +++ /dev/null @@ -1,84 +0,0 @@ -const deepIterator = require('deep-iterator').default; -const deepMerge = require('deepmerge'); -const isMergeableObject = require('./isMergeableObject'); -const jexl = require('jexl'); - -/** - * Generates one fully merged config file from multiple sources - * @type {module.ConfigGenerator} - */ -module.exports = class ConfigGenerator { - - constructor() {} - - loadConfigs(configPaths, pathPrefix) { - if (!Array.isArray(configPaths)) { - throw new Error('loadConfigs must he supplied with an array'); - } - - const configs = []; - const prefix = pathPrefix || '../'; - configPaths.forEach((configPath) => { - const path = `${prefix}${configPath}`; - - delete require.cache[require.resolve(path)]; - configs.push(require(path)); - }); - - return configs; - } - - getPropertyFromAllConfigs(property, configs) { - return configs.map((config) => { - return config[property] || {}; - }); - } - - getDataFromConfigs(configs) { - return this.getPropertyFromAllConfigs('data', configs); - } - - getAllocationsFromAllConfigs(configs) { - return this.getPropertyFromAllConfigs('layerAllocations', configs); - } - - allocateToLayers(configs) { - const accumulatedAllocations = deepMerge.all(this.getAllocationsFromAllConfigs(configs)); - Object.keys(accumulatedAllocations).forEach((key) => { - accumulatedAllocations[key] = Array.from(new Set(accumulatedAllocations[key])); - }); - return accumulatedAllocations; - } - - mergeConfigs(configs) { - return deepMerge.all(this.getDataFromConfigs(configs), { isMergeableObject }); - } - - async generateConfig(configPaths) { - const configs = this.loadConfigs(configPaths); - const mergedConfig = this.mergeConfigs(configs); - const data = await ConfigGenerator.processDeferredConfig(mergedConfig); - - return { - data: data, - layerAllocations: this.allocateToLayers(configs) - }; - } - - static async processExpression(expression, context) { - const normalised = expression.replace('!expression', ''); - return await jexl.eval(normalised, context); - } - - static async processDeferredConfig(config) { - const deepData = deepIterator(config); - for (let {parent, key, value} of deepData) { - if (typeof value === 'string' && value.indexOf('!expression ') > -1) { - parent[key] = await ConfigGenerator.processExpression(value, config); - } - } - - return config; - } - -}; diff --git a/libero-config/bin/distributeConfig.js b/libero-config/bin/distributeConfig.js deleted file mode 100644 index 2906acb0..00000000 --- a/libero-config/bin/distributeConfig.js +++ /dev/null @@ -1,37 +0,0 @@ -const ConfigGenerator = require('./ConfigGenerator'); -const ConfigDistributor = require('./ConfigDistributor'); -const fs = require('fs'); -const path = require('path'); -const {promisify} = require('util'); - -const readFileAsync = promisify(fs.readFile); - -const configSpecFilepath = path.join(path.resolve(__dirname, '..'), 'configRegister.json'); - -function useConfigSpec(rawData) { - const data = JSON.parse((rawData)); - const configPaths = data.configPaths; - - // Combine all configs specified in configPaths into one config - const configGenerator = new ConfigGenerator(configPaths); - - // Distribute defined parts of the config to specified technology layers - const configDistributor = new ConfigDistributor(); - return configDistributor.distribute(configPaths, configGenerator) - .catch((err) => { throw err; }); -} - -function distribute() { - return readFileAsync(configSpecFilepath) - .then(useConfigSpec) - .catch((err) => { - throw err; - }); -} - -module.exports = distribute; - -if (require.main === module) { - distribute(); -} - diff --git a/libero-config/bin/isMergeableObject.js b/libero-config/bin/isMergeableObject.js deleted file mode 100644 index 7c1dbb8a..00000000 --- a/libero-config/bin/isMergeableObject.js +++ /dev/null @@ -1,21 +0,0 @@ -const Color = require('color'); - -module.exports = function isMergeableObject(value) { - - // isNonNullObject and isNonNullObject copied from private deepmerge functions - - function isNonNullObject(value) { - return !!value && typeof value === 'object' - } - - function isSpecial(value) { - const stringValue = Object.prototype.toString.call(value); - - return stringValue === '[object RegExp]' - || stringValue === '[object Date]'; - } - - return isNonNullObject(value) && - !isSpecial(value) && - !(value instanceof Color); -}; diff --git a/libero-config/configRegister.json b/libero-config/configRegister.json deleted file mode 100644 index 042fd8c2..00000000 --- a/libero-config/configRegister.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configPaths": [ - "config--libero-default.js" - ] -} diff --git a/package-lock.json b/package-lock.json index eadcfe00..212cb647 100644 --- a/package-lock.json +++ b/package-lock.json @@ -868,6 +868,22 @@ "through2": "^2.0.3" } }, + "@libero/pattern-library-config-manager": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@libero/pattern-library-config-manager/-/pattern-library-config-manager-0.0.8.tgz", + "integrity": "sha512-gmX+9dbqKmQU3mUVl1OVsSfIG0y0TYegCPj+3prKjmcpXvGzf8Aej7go4HWrs4nSjAdpWu32JqdciMyAcssdkQ==", + "requires": { + "chai": "^4.2.0", + "chai-as-promised": "^7.1.1", + "color": "^3.1.0", + "deep-iterator": "^1.1.0", + "deepmerge": "^2.2.1", + "flat": "^4.1.0", + "jexl": "^1.1.4", + "mocha": "^5.2.0", + "sinon": "^7.1.1" + } + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -888,7 +904,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.3.0.tgz", "integrity": "sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA==", - "dev": true, "requires": { "type-detect": "4.0.8" } @@ -897,7 +912,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.0.0.tgz", "integrity": "sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w==", - "dev": true, "requires": { "@sinonjs/samsam": "2.1.0" }, @@ -906,7 +920,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.0.tgz", "integrity": "sha512-5x2kFgJYupaF1ns/RmharQ90lQkd2ELS8A9X0ymkAAdemYHGtI2KiUHG8nX2WU0T1qgnOU5YMqnBM2V7NUanNw==", - "dev": true, "requires": { "array-from": "^2.1.1" } @@ -916,8 +929,7 @@ "@sinonjs/samsam": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.2.tgz", - "integrity": "sha512-ZwTHAlC9akprWDinwEPD4kOuwaYZlyMwVJIANsKNC3QVp0AHB04m7RnB4eqeWfgmxw8MGTzS9uMaw93Z3QcZbw==", - "dev": true + "integrity": "sha512-ZwTHAlC9akprWDinwEPD4kOuwaYZlyMwVJIANsKNC3QVp0AHB04m7RnB4eqeWfgmxw8MGTzS9uMaw93Z3QcZbw==" }, "abbrev": { "version": "1.1.1", @@ -1126,8 +1138,7 @@ "array-from": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" }, "array-initial": { "version": "1.1.0", @@ -1246,8 +1257,7 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, "assign-symbols": { "version": "1.0.0", @@ -1366,7 +1376,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, "requires": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" @@ -1404,8 +1413,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base": { "version": "0.11.2", @@ -1529,7 +1537,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1567,8 +1574,7 @@ "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, "browser-sync": { "version": "2.26.3", @@ -1882,7 +1888,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -1896,7 +1901,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "dev": true, "requires": { "check-error": "^1.0.2" } @@ -1941,8 +1945,7 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "chokidar": { "version": "2.0.4", @@ -2112,7 +2115,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/color/-/color-3.1.0.tgz", "integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==", - "dev": true, "requires": { "color-convert": "^1.9.1", "color-string": "^1.5.2" @@ -2122,7 +2124,6 @@ "version": "1.9.2", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", - "dev": true, "requires": { "color-name": "1.1.1" } @@ -2130,14 +2131,12 @@ "color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", - "dev": true + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" }, "color-string": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", - "dev": true, "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -2161,8 +2160,7 @@ "commander": { "version": "2.15.1", "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" }, "commondir": { "version": "1.0.1", @@ -2191,8 +2189,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "1.6.2", @@ -2261,8 +2258,7 @@ "core-js": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", - "dev": true + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" }, "core-util-is": { "version": "1.0.2", @@ -2438,7 +2434,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, "requires": { "type-detect": "^4.0.0" } @@ -2447,7 +2442,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/deep-iterator/-/deep-iterator-1.1.0.tgz", "integrity": "sha1-NSJxc7OL4BtYDW98MnMrH9F2kII=", - "dev": true, "requires": { "babel-runtime": "^6.20.0" } @@ -2455,8 +2449,7 @@ "deepmerge": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "dev": true + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==" }, "default-compare": { "version": "1.0.0", @@ -2598,8 +2591,7 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, "dir-glob": { "version": "2.0.0", @@ -2971,8 +2963,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "esprima": { "version": "4.0.1", @@ -3418,7 +3409,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, "requires": { "is-buffer": "~2.0.3" }, @@ -3426,8 +3416,7 @@ "is-buffer": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", - "dev": true + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==" } } }, @@ -3642,8 +3631,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.2.4", @@ -4245,8 +4233,7 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, "get-stdin": { "version": "4.0.1", @@ -4256,7 +4243,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, @@ -4542,8 +4529,7 @@ "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, "gulp": { "version": "4.0.0", @@ -4928,8 +4914,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.0", @@ -4978,8 +4963,7 @@ "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, "home-or-tmp": { "version": "3.0.0", @@ -5185,7 +5169,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -5194,8 +5177,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", @@ -5299,7 +5281,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { @@ -5596,8 +5578,7 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "isexe": { "version": "2.0.0", @@ -5631,8 +5612,7 @@ "jexl": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/jexl/-/jexl-1.1.4.tgz", - "integrity": "sha1-Nc+G+IHqIZ0eIVx6QeLnR85u6KY=", - "dev": true + "integrity": "sha1-Nc+G+IHqIZ0eIVx6QeLnR85u6KY=" }, "js-base64": { "version": "2.4.8", @@ -5752,8 +5732,7 @@ "just-extend": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-3.0.0.tgz", - "integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==", - "dev": true + "integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==" }, "kind-of": { "version": "6.0.2", @@ -5995,8 +5974,7 @@ "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, "lodash.isfinite": { "version": "3.3.2", @@ -6059,8 +6037,7 @@ "lolex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-3.0.0.tgz", - "integrity": "sha512-hcnW80h3j2lbUfFdMArd5UPA/vxZJ+G8vobd+wg3nVEQA0EigStbYcrG030FJxL6xiDDPEkoMatV9xIh5OecQQ==", - "dev": true + "integrity": "sha512-hcnW80h3j2lbUfFdMArd5UPA/vxZJ+G8vobd+wg3nVEQA0EigStbYcrG030FJxL6xiDDPEkoMatV9xIh5OecQQ==" }, "longest-streak": { "version": "2.0.2", @@ -6335,9 +6312,8 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -6354,7 +6330,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, "requires": { "browser-stdout": "1.3.1", "commander": "2.15.1", @@ -6373,7 +6348,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -6382,7 +6356,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6396,7 +6369,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6405,7 +6377,6 @@ "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -6415,8 +6386,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mute-stdout": { "version": "1.0.1", @@ -6477,7 +6447,6 @@ "version": "1.4.6", "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.6.tgz", "integrity": "sha512-1GedetLKzmqmgwabuMSqPsT7oumdR77SBpDfNNJhADRIeA3LN/2RVqR4fFqwvzhAqcTef6PPCzQwITE/YQ8S8A==", - "dev": true, "requires": { "@sinonjs/formatio": "3.0.0", "just-extend": "^3.0.0", @@ -6489,8 +6458,7 @@ "lolex": { "version": "2.7.5", "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==" } } }, @@ -6819,7 +6787,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, "requires": { "wrappy": "1" } @@ -6882,7 +6849,7 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, @@ -6897,7 +6864,7 @@ }, "os-tmpdir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, @@ -7063,9 +7030,8 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -7104,7 +7070,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "dev": true, "requires": { "isarray": "0.0.1" } @@ -7131,8 +7096,7 @@ "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, "performance-now": { "version": "2.1.0", @@ -7760,8 +7724,7 @@ "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { "version": "0.13.3", @@ -8163,7 +8126,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -8371,7 +8334,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, "requires": { "is-arrayish": "^0.3.1" }, @@ -8379,8 +8341,7 @@ "is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" } } }, @@ -8388,7 +8349,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.1.1.tgz", "integrity": "sha512-iYagtjLVt1vN3zZY7D8oH7dkjNJEjLjyuzy8daX5+3bbQl8gaohrheB9VfH1O3L6LKuue5WTJvFluHiuZ9y3nQ==", - "dev": true, "requires": { "@sinonjs/commons": "^1.2.0", "@sinonjs/formatio": "^3.0.0", @@ -8405,7 +8365,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -8951,7 +8910,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -9589,7 +9548,7 @@ }, "tar": { "version": "2.2.1", - "resolved": "http://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { @@ -9601,8 +9560,7 @@ "text-encoding": { "version": "0.6.4", "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "dev": true + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=" }, "textextensions": { "version": "2.4.0", @@ -9828,8 +9786,7 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "typedarray": { "version": "0.0.6", @@ -10405,7 +10362,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { @@ -10416,8 +10373,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "0.2.1", diff --git a/package.json b/package.json index d695120b..c3235821 100644 --- a/package.json +++ b/package.json @@ -38,5 +38,8 @@ }, "engines": { "node": ">=10.12" + }, + "dependencies": { + "@libero/pattern-library-config-manager": "0.0.8" } } diff --git a/source/css/sass/_normalize.scss b/source/css/sass/_normalize.scss index 349bf8d4..b87afe03 100644 --- a/source/css/sass/_normalize.scss +++ b/source/css/sass/_normalize.scss @@ -2,6 +2,7 @@ @import "mixins/typography"; @import "variables/color"; @import "vendor/normalize.css/normalize"; +@import "functions/colors"; *, *:before, @@ -15,39 +16,39 @@ body { } body { - background-color: $color-background; - color: $color-text-normal; + background-color: get-color(background); + color: get-color(normal); text-rendering: optimizeLegibility; @include body-typography(); } h1 { - @include h1-typography(); + @include heading-level-typography(1, 48px); @include h1-spacing(); } h2 { - @include h2-typography(); + @include heading-level-typography(1, 30px); @include h2-spacing(); } h3 { - @include h3-typography(); + @include heading-level-typography(3); @include h3-spacing(); } h4 { - @include h4-typography(); + @include heading-level-typography(4); @include h4-spacing(); } h5 { - @include h5-typography(); + @include heading-level-typography(5); @include h5-spacing(); } h6 { - @include h6-typography(); + @include heading-level-typography(6); @include h6-spacing(); } @@ -56,7 +57,7 @@ p { } a { - color: $color-primary-normal; + color: get-color(primary-normal); text-decoration: none; } diff --git a/source/css/sass/functions/_baselinegrid.scss b/source/css/sass/functions/_baselinegrid.scss new file mode 100644 index 00000000..4859b9bc --- /dev/null +++ b/source/css/sass/functions/_baselinegrid.scss @@ -0,0 +1,6 @@ +@import "../variables/baselinegrid"; +@import "maps"; + +@function get-baselinegrid-measure ($name, $map: $baselinegrid) { + @return get-value-from-map($map, $name); +} diff --git a/source/css/sass/functions/_breakpoints.scss b/source/css/sass/functions/_breakpoints.scss new file mode 100644 index 00000000..ac1172d3 --- /dev/null +++ b/source/css/sass/functions/_breakpoints.scss @@ -0,0 +1,6 @@ +@import "../variables/breakpoint"; +@import "maps"; + +@function get-breakpoint($name, $map: $breakpoint) { + @return get-value-from-map($map, $name); +} diff --git a/source/css/sass/functions/_colors.scss b/source/css/sass/functions/_colors.scss new file mode 100644 index 00000000..460e28c8 --- /dev/null +++ b/source/css/sass/functions/_colors.scss @@ -0,0 +1,6 @@ +@import "../variables/color"; +@import "maps"; + +@function get-color($name, $map: $color) { + @return get-value-from-map($map, $name); +} diff --git a/source/css/sass/functions/_grid.scss b/source/css/sass/functions/_grid.scss index 8b73dc89..c93017b8 100644 --- a/source/css/sass/functions/_grid.scss +++ b/source/css/sass/functions/_grid.scss @@ -1,3 +1,10 @@ +@import "../variables/grid"; +@import "maps"; + +@function get-grid-measure ($name, $map: $grid) { + @return get-value-from-map($map, $name); +} + @function get-overall-width($columns) { @return calc((#{$columns} * var(--GRID-COLUMN-WIDTH)) + (#{$columns - 1} * var(--GRID-COLUMN-GAP))); } diff --git a/source/css/sass/functions/_maps.scss b/source/css/sass/functions/_maps.scss new file mode 100644 index 00000000..c13c93ef --- /dev/null +++ b/source/css/sass/functions/_maps.scss @@ -0,0 +1,16 @@ +@function get-value-from-map($map, $key) { + + @if type_of($map) == "map" and map_has_key($map, $key) { + @return map_get($map, $key); + } + + @return "[Not found]"; +} + +@function get-value-from-map-or-pass-through($map, $keyOrDefault) { + $value: get-value-from-map($map, $keyOrDefault); + @if $value == "[Not found]" { + $value: $keyOrDefault; + } + @return $value; +} diff --git a/source/css/sass/functions/_types.scss b/source/css/sass/functions/_types.scss index d2d5a22b..85d3acf5 100644 --- a/source/css/sass/functions/_types.scss +++ b/source/css/sass/functions/_types.scss @@ -1,5 +1,27 @@ -@import "../mixins/types"; @import "../variables/font"; -$rem-baseline: $font-size-base; +@function get-font-size($designation) { + @if map_has_key($font, $designation) { + @return map_get($font, $designation); + } + + @error "Key #{$designation} not found in the $font map."; +} + +@function is-a-px-number($candidate) { + $passed: type_of($candidate) == "number"; + $passed: $passed and type_of($candidate / 1px); + $passed: $passed and unitless($candidate / 1px); + @return $passed; +} + +@function is-a-rem-number($candidate) { + $passed: type_of($candidate) == "number"; + $passed: $passed and type_of($candidate / 1rem); + $passed: $passed and unitless($candidate / 1rem); + @return $passed; +} + +//$rem-baseline: $font-size-base; +$rem-baseline: get-font-size(size-base); $rem-fallback: true; diff --git a/source/css/sass/mixins/_colors.scss b/source/css/sass/mixins/_colors.scss new file mode 100644 index 00000000..c3e906a5 --- /dev/null +++ b/source/css/sass/mixins/_colors.scss @@ -0,0 +1,26 @@ +@import "../variables/color"; +@import "../variables/custom-properties--color"; +@import "../functions/maps"; +@import "../mixins/validation"; + +@mixin _set-color-based-property($property, $color, $map) { + $value: get-value-from-map-or-pass-through($map, $color); + + @if type_of($value) == "color" { + #{$property}: $value; + @if map_has_key($map, $color) { + #{$property}: var(--color-#{$color}); + } + } @else { + @include _error("Trying to set a non-color value to property `#{$property}`"); + } + +} + +@mixin set-color($designation, $map: $color) { + @include _set-color-based-property(color, $designation, $map); +} + +@mixin set-background-color($designation, $map: $color) { + @include _set-color-based-property(background-color, $designation, $map); +} diff --git a/source/css/sass/mixins/_media-query.scss b/source/css/sass/mixins/_media-query.scss index a1dbc103..cc6c1eb8 100644 --- a/source/css/sass/mixins/_media-query.scss +++ b/source/css/sass/mixins/_media-query.scss @@ -1,14 +1,16 @@ @import "../variables/breakpoint"; @import "../variables/font"; +@import "../functions/breakpoints"; +@import "types"; -$mq-base-font-size: $font-size-base; +$mq-base-font-size: get-font-size(size-base); $mq-breakpoints: ( - x-small: $breakpoint-site-x_small, - small: $breakpoint-site-small, - medium: $breakpoint-site-medium, - wide: $breakpoint-site-wide, - x-wide: $breakpoint-site-x_wide, + x-small: get-breakpoint(x_small), + small: get-breakpoint(small), + medium: get-breakpoint(medium), + wide: get-breakpoint(wide), + x-wide: get-breakpoint(x_wide), ); @import "../vendor/sass-mq/_mq"; diff --git a/source/css/sass/mixins/_spacing.scss b/source/css/sass/mixins/_spacing.scss index d3648970..961198e2 100644 --- a/source/css/sass/mixins/_spacing.scss +++ b/source/css/sass/mixins/_spacing.scss @@ -3,11 +3,15 @@ @import "sizes"; @import "types"; @import "../functions/validation"; +@import "../functions/baselinegrid"; +@import "../functions/grid"; @import "../mixins/media-query"; @import "../variables/baselinegrid"; @import "../variables/breakpoint"; @import "../variables/grid"; +$_default-baselinegrid-map: $baselinegrid; + // Fallbacks for CSS logical properties contained within this mixin require the following treatment of HTML dir attributes: // - document level: always specified, via the HTML element // - block level: specified on every element within a block describing a direction switch. @@ -94,33 +98,21 @@ } // blg stands for "baseline grid" +@mixin blg-spacing($dimension, $level, $type: "padding", $map: $_default-baselinegrid-map) { -@mixin blg-spacing($dimension, $level, $type: "padding") { - @if $type == "padding" { - @if $level == "extra-small" { - @include padding($baselinegrid-space-extra-small, $dimension); - } @else if $level == "small" { - @include padding($baselinegrid-space-small, $dimension); - } @else if $level == "smallish" { - @include padding($baselinegrid-space-smallish, $dimension); - } @else if $level == "medium" { - @include padding($baselinegrid-space-medium, $dimension); - } @else if $level == "large" { - @include padding($baselinegrid-space-large, $dimension); - } - } @else if $type == "margin" { - @if $level == "extra-small" { - @include margin($baselinegrid-space-extra-small, $dimension); - } @else if $level == "small" { - @include margin($baselinegrid-space-small, $dimension); - } @else if $level == "smallish" { - @include margin($baselinegrid-space-smallish, $dimension); - } @else if $level == "medium" { - @include margin($baselinegrid-space-medium, $dimension); - } @else if $level == "large" { - @include margin($baselinegrid-space-large, $dimension); - } + $baselinegrid-measure: get-baselinegrid-measure($level, $map); + @if $baselinegrid-measure == "[Not found]" { + @include _error("Expected supplied level `#{$level}` to be a baselinegrid map key"); } + + @if $type == "margin" { + @include margin($baselinegrid-measure, $dimension); + } @else if $type == "padding" { + @include padding($baselinegrid-measure, $dimension); + } @else { + @include _error("Supplied type was neither margin nor padding: got `#{$type}`"); + } + } @mixin blg-pad-top--small-to-medium { @@ -193,49 +185,49 @@ } -@mixin blg-column-container() { +@mixin blg-column-container { @include blg-margin-bottom--medium-to-large(); } -@mixin h1-spacing() { +@mixin h1-spacing { margin: 0; } -@mixin h2-spacing() { +@mixin h2-spacing { margin: 0; @include padding(21px, "block-end"); @include padding(21px, "block-start"); } -@mixin h3-spacing() { +@mixin h3-spacing { margin: 0; @include blg-spacing("block-start", "extra-small"); @include blg-spacing("block-end", "extra-small"); } -@mixin h4-spacing() { +@mixin h4-spacing { margin: 0; @include blg-spacing("block-start", "extra-small"); @include blg-spacing("block-end", "extra-small"); } -@mixin h5-spacing() { +@mixin h5-spacing { margin: 0; @include blg-spacing("block-start", "extra-small"); @include blg-spacing("block-end", "extra-small"); } -@mixin h6-spacing() { +@mixin h6-spacing { margin: 0; @include padding(10px, "block-start"); @include padding(14px, "block-end"); } -@mixin body-spacing() { +@mixin body-spacing { margin: 0; @include blg-spacing("block-end", "small", "margin"); } -@mixin small-spacing() { +@mixin small-spacing { @include blg-spacing("block-end", "small"); } diff --git a/source/css/sass/mixins/_types.scss b/source/css/sass/mixins/_types.scss index b507c2a2..c2fe0564 100644 --- a/source/css/sass/mixins/_types.scss +++ b/source/css/sass/mixins/_types.scss @@ -1,9 +1,7 @@ +@import "../functions/types"; @import "../variables/font"; @import "../vendor/sass-rem/rem"; -$rem-baseline: $font-size-base; -$rem-fallback: true; - // Overridden to apply https://github.com/pierreburel/sass-rem/pull/12 @mixin rem($properties, $values...) { diff --git a/source/css/sass/mixins/_typography.scss b/source/css/sass/mixins/_typography.scss index 0689fbc5..72f657f5 100644 --- a/source/css/sass/mixins/_typography.scss +++ b/source/css/sass/mixins/_typography.scss @@ -1,57 +1,89 @@ +@import "../functions/maps"; +@import "../functions/baselinegrid"; +@import "../functions/colors"; @import "../mixins/types"; @import "../variables/baselinegrid"; @import "../variables/color"; @import "../variables/font"; @import "spacing"; +$_default-font-map: $font; +$_default-color-map: $color; + @mixin set-font-size-and-line-height($font-size, $block-size: $baselinegrid-space-small) { @include rem(font-size, $font-size); line-height: $block-size / $font-size; } -@mixin _heading-base-typography() { - font-family: $font-secondary; - font-weight: 600; -} +/* TODO: Consider a `strict` param that would use get-value-from-map rather than get-value-from-map-or-pass-through. -@mixin h1-typography() { - @include _heading-base-typography(); - @include set-font-size-and-line-height($font-size-h1, 48px); -} + This may allow better centralisation of the core bits of what happens when the key is not found in the map + */ +@mixin font-size($size, $map: $_default-font-map) { + $font-size: get-value-from-map-or-pass-through($map, $size); + @if is-a-px-number($font-size) or is-a-rem-number($font-size) { + @include rem(font-size, $font-size); + @if map_has_key($map, $size) { + font-size: var(--font-#{$size}); + } + + } @else { + @include _error("Font size must be set using a 'px'-suffixed number or a 'rem'-suffixed number."); + } -@mixin h2-typography() { - @include _heading-base-typography(); - @include set-font-size-and-line-height($font-size-h2, 30px); } -@mixin h3-typography() { - @include _heading-base-typography(); - @include set-font-size-and-line-height($font-size-h3); +@mixin font-family($designation, $map: $_default-font-map) { + $font-family: get-value-from-map($map, $designation); + @if $font-family == "[Not found]" { + @include _error("Font family key `#{$designation}` not found in map"); + } @else { + font-family: unquote($font-family); + font-family: var(--font-#{$designation}); + } } -@mixin h4-typography() { - @include _heading-base-typography(); - @include set-font-size-and-line-height($font-size-h4); +@mixin set-font-size-and-vertical-height($font-size, $vertical-height: get-baselinegrid-measure(small), $map: $_default-font-map) { + @include font-size($font-size, $map); + + @if map_has_key($map, $font-size) { + line-height: $vertical-height / map_get($map, $font-size); + } @else { + line-height: $vertical-height / $font-size; + } } -@mixin h5-typography() { - @include _heading-base-typography(); - @include set-font-size-and-line-height($font-size-h5); +@mixin _heading-base-typography() { + @include font-family(family-secondary); + font-weight: 600; } -@mixin h6-typography() { - @include _heading-base-typography(); - @include set-font-size-and-line-height($font-size-h6); +@mixin heading-level-typography($level, $line-height: get-baselinegrid-measure(small), $map: $_default-font-map) { + @if type_of($level) != "number" or not unitless($level) or $level < 1 or $level > 6 { + @include _error("Invalid heading level `#{$level}` supplied"); + } @else { + + $key: size-h#{$level}; + @if map_has_key($map, $key) { + $font-size: map_get($map, $key); + @include _heading-base-typography(); + @include set-font-size-and-vertical-height($font-size, $line-height, $map); + font-size: var(--font-#{$key}); + } @else { + @include _error("Font map is missing the definition of h#{$level} font size"); + } + + } } @mixin body-typography() { - font-family: $font-primary; - @include set-font-size-and-line-height($font-size-base); + @include font-family(family-primary); + @include set-font-size-and-vertical-height(size-base); font-weight: normal; } @mixin small-typography() { - font-family: $font-primary; + @include font-family(family-primary); font-style: normal; @include set-font-size-and-line-height(11px); } @@ -93,19 +125,24 @@ @mixin _label-typography($color, $uppercase: true) { color: $color; - font-family: $font-secondary; + @include font-family(family-secondary); font-weight: normal; - @include set-font-size-and-line-height($font-size-label); - letter-spacing: $font-letterspacing-label; + @include set-font-size-and-vertical-height(size-label); + letter-spacing: #{letterspacing-label}; @if $uppercase { text-transform: uppercase; } } -@mixin label-content-typography($color: $color-text-secondary, $uppercase: true) { - @include _label-typography($color, $uppercase); +@mixin label-content-typography($color: text-secondary, $uppercase: true, $map: $_default-color-map) { + $col: get-color($color, $map); + @if $col != "[Not found]" { + @include _label-typography($col, $uppercase); + } @else { + @include _error("Can't resolve `#{$color}` in the color map"); + } } @mixin label-tag-typography() { - @include _label-typography($color-primary-normal); + @include _label-typography(get-color(primay-normal)); } diff --git a/test/libero-config/ConfigDistributor.spec.js b/test/libero-config/ConfigDistributor.spec.js deleted file mode 100644 index c3f2079b..00000000 --- a/test/libero-config/ConfigDistributor.spec.js +++ /dev/null @@ -1,86 +0,0 @@ -const chai = require('chai'); -const chaiAsPromised = require('chai-as-promised'); -const sinon = require('sinon'); - -const fixtures = require('./fixtures/configFixtures'); -const ConfigDistributor = require('../../libero-config/bin/ConfigDistributor'); - -const spy = sinon.spy; - -chai.use(chaiAsPromised); -const expect = chai.expect; - -const standAloneConfigFixtureFilePath = './fixtures/configFixtureStandAlone'; -const standAloneConfigFixture = require(standAloneConfigFixtureFilePath); - -describe('A DistributeConfig class', () => { - - context('instantiated object', () => { - - let configDistributor; - - beforeEach(() => { - configDistributor = new ConfigDistributor(); - }); - - describe('distribute method', () => { - - let configPaths; - - it('initiates config generation with the config paths supplied', () => { - const configGeneratorMock = { - generateConfig: () => { - return Promise.resolve(standAloneConfigFixture); - }, - }; - spy(configGeneratorMock, 'generateConfig'); - - const configPaths = fixtures.configPaths; - return configDistributor.distribute(configPaths, configGeneratorMock).then(() => { - expect(configGeneratorMock.generateConfig.calledOnceWithExactly(configPaths)).to.be.true; - }); - }); - - }); - - }); - - describe('processForSass static method', () => { - - context('when supplied with a JavaScript object defining data for SASS variables', () => { - - let sassConfigFixture; - - beforeEach(() => { - sassConfigFixture = fixtures.sassConfigToProcess.input; - }); - - it('correctly converts the JavaScript into a string wrapping corresponding SASS variable declarations', () => { - const processed = ConfigDistributor.processForSass(sassConfigFixture); - expect(processed).to.deep.equal(fixtures.sassConfigToProcess.expected); - }); - - }); - - }); - - describe('processForJs static method', () => { - - context('when supplied with a JavaScript object defining data for the JavaScript layer', () => { - - let jsConfigFixture; - - beforeEach(() => { - jsConfigFixture = fixtures.jsConfigToProcess.input; - }); - - it('correctly converts the JavaScript into the appropriate JSON', () => { - const processed = ConfigDistributor.processForJs(['breakpoints'], jsConfigFixture); - expect(processed).to.deep.equal(JSON.stringify(fixtures.jsConfigToProcess.input)); - }); - - }); - - }); - -}); diff --git a/test/libero-config/ConfigGenerator.spec.js b/test/libero-config/ConfigGenerator.spec.js deleted file mode 100644 index a69bcdf4..00000000 --- a/test/libero-config/ConfigGenerator.spec.js +++ /dev/null @@ -1,165 +0,0 @@ -const chai = require('chai'); -const chaiAsPromised = require('chai-as-promised'); - -const expect = chai.expect; -chai.use(chaiAsPromised); - -const Color = require('color'); - -const fixtures = require('./fixtures/configFixtures'); -const ConfigGenerator = require('../../libero-config/bin/ConfigGenerator'); - -describe('A ConfigGenerator class', () => { - - context('instansiated object', () => { - - let configGenerator; - - beforeEach(() => { - configGenerator = new ConfigGenerator(); - }); - - describe('loadConfigs method', () => { - - context('when not supplied an array', () => { - - it('throws with the message "loadConfigs must he supplied with an array"', () => { - expect(() => { - configGenerator.loadConfigs(null); - }).to.throw('loadConfigs must he supplied with an array'); - }); - - }); - - context('when supplied an array', () => { - - it('does not throw with the message "loadConfigs must he supplied with an array"', () => { - expect(() => { - configGenerator.loadConfigs([]); - }).not.to.throw('loadConfigs must he supplied with an array'); - }); - - context('when a value in the supplied array does not resolve to a file system path', () => { - - it('throws with the message saying the module cannot be found', () => { - expect(() => { - configGenerator.loadConfigs(['./path/to/non-existant/file']); - }).to.throw(/Cannot find module/); - }); - - }); - - context('when all values in the supplied array resolve to a file system path', () => { - - it('does not throw', () => { - expect(() => { - configGenerator.loadConfigs(['configFixtures.js'], `${__dirname}/fixtures/`); - }).not.to.throw(); - }); - - }); - - }); - - }); - - describe('mergeConfigs method', () => { - - let firstConfig; - let secondConfig; - let merged; - - beforeEach(() => { - firstConfig = fixtures.configsToMerge.firstConfig; - secondConfig = fixtures.configsToMerge.secondConfig; - merged = configGenerator.mergeConfigs([firstConfig, secondConfig]); - - }); - - it('performs a deep merge using a list of config objects', () => { - expect(merged.objects).to.have.lengthOf(6); - expect(merged.objects[0]).to.deep.equal(firstConfig.data.objects[0]); - expect(merged.objects[1]).to.deep.equal(firstConfig.data.objects[1]); - expect(merged.objects[2]).to.deep.equal(firstConfig.data.objects[2]); - expect(merged.objects[3]).to.deep.equal(secondConfig.data.objects[0]); - expect(merged.objects[4]).to.deep.equal(secondConfig.data.objects[1]); - expect(merged.objects[5]).to.deep.equal(secondConfig.data.objects[2]); - expect(merged.objects[6]).to.deep.equal(secondConfig.data.objects[3]); - expect(merged.additionalProperty).to.equal(secondConfig.data.additionalProperty); - }); - - it('ignores instances of Color', () => { - expect(merged.color).to.be.an.instanceOf(Color); - }); - - context('when passed object properties that would cause a merge conflict', () => { - - it('the one passed last wins', () => { - expect(merged.clash).to.equal(secondConfig.data.clash); - }); - - }); - - }); - - describe('allocateToLayers method', () => { - - let allConfigsAllocations; - let mergedAllocations; - - beforeEach(() => { - allConfigsAllocations = fixtures.configLayerAllocations; - mergedAllocations = configGenerator.allocateToLayers(allConfigsAllocations); - }); - - it('correctly merges allocations from all configs', () => { - expect(mergedAllocations.sass).to.be.an('array').that.has.a.lengthOf(3); - expect(mergedAllocations.sass).to.include('breakpoints'); - expect(mergedAllocations.sass).to.include('colors'); - expect(mergedAllocations.sass).to.include('grid'); - - expect(mergedAllocations.js).to.be.an('array').that.has.a.lengthOf(2); - expect(mergedAllocations.js).to.include('breakpoints'); - expect(mergedAllocations.js).to.include('colors'); - - expect(mergedAllocations.template).to.be.an('array').that.has.a.lengthOf(1); - expect(mergedAllocations.template).to.include('grid'); - }); - - }); - - }); - - describe('processDeferredConfig static method', () => { - - let configWithNoDeferrals; - let configWithDeferrals; - - beforeEach(() => { - configWithNoDeferrals = fixtures.configWithNoDeferrals; - configWithDeferrals = fixtures.configWithDeferrals; - }); - - context('when passed config containing a value beginning "!expression"', () => { - - it('evaluates that expression within the context of config', () => { - return expect( - ConfigGenerator.processDeferredConfig(configWithDeferrals), - ).to.eventually.have.own.property('derivedValue', 300); - }); - - }); - - context('when passed config containing a value not beginning "!expression"', () => { - - it('passes that value through unchanged', () => { - return expect( - ConfigGenerator.processDeferredConfig(configWithDeferrals), - ).to.eventually.have.own.property('rootValue', 10); - }); - - }); - - }); - -}); diff --git a/test/libero-config/fixtures/configFixtureStandAlone.js b/test/libero-config/fixtures/configFixtureStandAlone.js deleted file mode 100644 index 2128588f..00000000 --- a/test/libero-config/fixtures/configFixtureStandAlone.js +++ /dev/null @@ -1,22 +0,0 @@ -const Color = require('color'); - -const config = {data: {}}; - -config.data.baselinegrid = {space: {}}; -config.data.baselinegrid.space.extra_small_in_px = 12; -config.data.baselinegrid.space.small_in_px = '!expression baselinegrid.space.extra_small_in_px * 2'; - -config.data.breakpoints = {site: {}}; -config.data.breakpoints.site.x_small = 320; -config.data.breakpoints.site.small = 480; - -config.data.color = {primary: {}, text: {}}; -config.data.color.text.normal = Color('#212121'); - -config.layerAllocations = { - sass: ['baselinegrid', 'breakpoints', 'color'], - js: ['color', 'breakpoints'], - template: ['breakpoints'], -}; - -module.exports = config; diff --git a/test/libero-config/fixtures/configFixtures.js b/test/libero-config/fixtures/configFixtures.js deleted file mode 100644 index 5e68e659..00000000 --- a/test/libero-config/fixtures/configFixtures.js +++ /dev/null @@ -1,125 +0,0 @@ -const Color = require('color'); - -const firstGenericConfig = { - data: { - clash: 'config 1 clashing value', - objects: [ - { - id: 1, - }, - { - id: 2, - }, - { - id: 3, - }, - ], - color: Color('#663399'), - }, -}; - -const secondGenericConfig = { - data: { - clash: 'config 2 clashing value', - additionalProperty: 'I am only in one of the configs', - objects: [ - { - id: 4, - }, - { - id: 5, - }, - { - id: 6, - }, - ], - }, -}; - -module.exports = { - - configPaths: [ - './config--libero', - './config--custom', - ], - - configWithNoDeferrals: { - stringProperty: 'string property', - nestedStringProperty: { - nested: { - string: { - property: 'nested string property value', - }, - }, - }, - }, - - configWithDeferrals: { - rootValue: 10, - derivedValue: '!expression rootValue * 30', - }, - - configsToMerge: { - firstConfig: firstGenericConfig, - secondConfig: secondGenericConfig, - }, - - configsWithData: { - firstConfig: firstGenericConfig, - secondConfig: secondGenericConfig, - }, - - configLayerAllocations: [ - { - layerAllocations: { - sass: ['breakpoints', 'colors'], - js: ['breakpoints'], - template: ['grid'], - }, - }, - { - layerAllocations: { - sass: ['breakpoints', 'colors', 'grid'], - js: ['breakpoints', 'colors'], - }, - }, - ], - - sassConfigToProcess: { - input: { - breakpoints: { - site: { - 'x_small': 320, - small: 480, - medium: 730, - wide: 900, - 'x_wide': 1400, - 'xx_wide': 1600, - }, - }, - }, - expected: '$breakpoints-site-x_small: 320;\n' - + '$breakpoints-site-small: 480;\n' - + '$breakpoints-site-medium: 730;\n' - + '$breakpoints-site-wide: 900;\n' - + '$breakpoints-site-x_wide: 1400;\n' - + '$breakpoints-site-xx_wide: 1600;\n', - }, - - jsConfigToProcess: { - input: { - breakpoints: { - site: { - 'x_small': 320, - small: 480, - medium: 730, - wide: 900, - 'x_wide': 1400, - 'xx_wide': 1600, - }, - }, - }, - - }, - -}; diff --git a/test/sass/mixins/colors.spec.scss b/test/sass/mixins/colors.spec.scss new file mode 100644 index 00000000..ef14f8cf --- /dev/null +++ b/test/sass/mixins/colors.spec.scss @@ -0,0 +1,157 @@ +@import "../test"; +@import "../../../source/css/sass/mixins/colors"; + +@include describe("@mixin set-color") { + + @include it("sets the color using the map's value when the argument is a map key, and the corresponding value is a color") { + + @include assert() { + + $fixture: ( + some-color: rgba(11, 22, 33, 0.44), + ); + + @include output { + @include set-color(some-color, $fixture); + } + + @include expect { + color: rgba(11, 22, 33, 0.44); + color: var(--color-#{some-color}); + } + + } + + } + + @include it("sets the color directly when the argument is a color value") { + + @include assert() { + + @include output { + @include set-color(rgb(55, 55, 55)); + } + + @include expect { + color: rgb(55, 55, 55); + } + + } + + } + + @include it("errors if the argument is a map key resolving to a non-color value") { + + @include assert() { + + $fixture: (unused-key: unused-value); + + @include output { + @include set-color(not-a-color, $fixture); + } + + @include expect { + _error: "Trying to set a non-color value to property `color`"; + } + + } + + } + + @include it("errors if the argument is neither a map key nor a color value") { + + @include assert() { + + $fixture: (key-to-not-a-color: not-a-color); + + @include output { + @include set-color(key-to-not-a-color, $fixture); + } + + @include expect { + _error: "Trying to set a non-color value to property `color`"; + } + + } + + } + +} + +@include describe("@mixin set-background-color") { + + @include it("sets the background-color using the map's value when the argument is a map key, and the corresponding value is a color") { + + @include assert() { + + $fixture: ( + some-color: rgba(11, 22, 33, 0.44), + ); + + @include output { + @include set-background-color(some-color, $fixture); + } + + @include expect { + background-color: rgba(11, 22, 33, 0.44); + background-color: var(--color-#{some-color}); + } + + } + + } + + @include it("sets the background-color directly when the argument is a color value") { + + @include assert() { + + @include output { + @include set-background-color(rgb(55, 55, 55)); + } + + @include expect { + background-color: rgb(55, 55, 55); + } + + } + + } + + @include it("errors if the argument is a map key resolving to a non-color value") { + + @include assert() { + + $fixture: (unused-key: unused-value); + + @include output { + @include set-background-color(not-a-color, $fixture); + } + + @include expect { + _error: "Trying to set a non-color value to property `background-color`"; + } + + } + + } + + @include it("errors if the argument is neither a map key nor a color value") { + + @include assert() { + + $fixture: (key-to-not-a-color: not-a-color); + + @include output { + @include set-background-color(key-to-not-a-color, $fixture); + } + + @include expect { + _error: "Trying to set a non-color value to property `background-color`"; + } + + } + + } + +} + diff --git a/test/sass/mixins/spacing.spec.scss b/test/sass/mixins/spacing.spec.scss index fcf05382..8aae2789 100644 --- a/test/sass/mixins/spacing.spec.scss +++ b/test/sass/mixins/spacing.spec.scss @@ -2539,3 +2539,187 @@ } } + +@include describe("@mixin blg-spacing") { + + $fixture-map: ( + space-extra_small: 16px, + space-small: 32px, + space-smallish: 48px, + space-medium: 64px, + space-large: 80px, + space-extra_large: 96px, + ); + $fixture-dimension: block-start; + $fixture-level: space-small; + $fixture-type: padding; + + $rem-number-by-level: ( + space-extra_small: 1rem, + space-small: 2rem, + space-smallish: 3rem, + space-medium: 4rem, + space-large: 5rem, + space-extra_large: 6rem, + ); + + @include it("errors if the type supplied is neither padding nor margin") { + + @include assert() { + + @include output { + @include blg-spacing($fixture-dimension, $fixture-level, neither-padding-nor-margin, $fixture-map); + } + + @include contains { + _error: "Supplied type was neither margin nor padding: got `neither-padding-nor-margin`"; + } + + } + + } + + @include it("errors if the level supplied is not a key in the map") { + + @include assert() { + + @include output { + @include blg-spacing($fixture-dimension, not-a-map-key, $fixture-type, $fixture-map); + } + + @include contains { + _error: "Expected supplied level `not-a-map-key` to be a baselinegrid map key"; + } + + } + + } + + @include it("sets padding-block-start correctly when given padding as the type and block-start as the dimension") { + + @include assert() { + @include output() { + @include blg-spacing(block-start, $fixture-level, padding, $fixture-map); + } + + @include contains() { + padding-block-start: map_get($rem-number-by-level, $fixture-level); + } + + } + + } + + @include it("sets margin-block-start correctly when given margin as the type and block-start as the dimension") { + + @include assert() { + + @include output { + @include blg-spacing(block-start, $fixture-level, margin, $fixture-map); + } + + @include contains { + margin-block-start: map_get($rem-number-by-level, $fixture-level); + } + + } + + } + + @include it("sets the spacing quantity as extra-small when supplied with the level extra-small") { + + @include assert() { + + @include output { + @include blg-spacing($fixture-dimension, space-extra-small, $fixture-type, $fixture-map); + } + + @include contains { + #{$fixture-type}-#{$fixture-dimension}: map_get($rem-number-by-level, space-extra-small); + } + + } + + } + + @include it("sets the spacing quantity as small when supplied with the level small") { + + @include assert() { + + @include output { + @include blg-spacing($fixture-dimension, space-small, $fixture-type, $fixture-map); + } + + @include contains { + #{$fixture-type}-#{$fixture-dimension}: map_get($rem-number-by-level, space-small); + } + + } + + } + + @include it("sets the spacing quantity as smallish when supplied with the level smallish") { + + @include assert() { + + @include output { + @include blg-spacing($fixture-dimension, space-smallish, $fixture-type, $fixture-map); + } + + @include contains { + #{$fixture-type}-#{$fixture-dimension}: map_get($rem-number-by-level, space-smallish); + } + + } + + } + + @include it("sets the spacing quantity as medium when supplied with the level medium") { + + @include assert() { + + @include output { + @include blg-spacing($fixture-dimension, space-medium, $fixture-type, $fixture-map); + } + + @include contains { + #{$fixture-type}-#{$fixture-dimension}: map_get($rem-number-by-level, space-medium); + } + + } + + } + + @include it("sets the spacing quantity as large when supplied with the level large") { + + @include assert() { + + @include output { + @include blg-spacing($fixture-dimension, space-large, $fixture-type, $fixture-map); + } + + @include contains { + #{$fixture-type}-#{$fixture-dimension}: map_get($rem-number-by-level, space-large); + } + + } + + } + + @include it("sets the spacing quantity as extra large when supplied with the level extra large") { + + @include assert() { + + @include output { + @include blg-spacing($fixture-dimension, space-extra-large, $fixture-type, $fixture-map); + } + + @include contains { + #{$fixture-type}-#{$fixture-dimension}: map_get($rem-number-by-level, space-extra-large); + } + + } + + } + +} diff --git a/test/sass/mixins/typography.spec.scss b/test/sass/mixins/typography.spec.scss index a31fbfc6..448b945c 100644 --- a/test/sass/mixins/typography.spec.scss +++ b/test/sass/mixins/typography.spec.scss @@ -1,6 +1,447 @@ @import "../test"; @import "../../../source/css/sass/mixins/typography"; +@include describe("@mixin font-size") { + + @include it("sets the font size using the map's value when the argument is a map key") { + + @include assert() { + + $fixture: ( + some-size: 16px, + ); + + @include output { + @include font-size(some-size, $fixture); + } + + @include expect { + font-size: 16px; + font-size: 1rem; + font-size: var(--font-some-size); + } + + } + + } + + @include it("sets the font size using the argument directly when it's not a map key") { + + @include assert() { + + $fixture: ( + some-size: 16px, + ); + + @include output { + @include font-size(32px, $fixture); + } + + @include expect { + font-size: 32px; + font-size: 2rem; + } + + } + + } + + @include it("can accommodate rem numbers") { + + @include assert() { + + $fixture: ( + some-size: 1rem, + ); + + @include output { + @include font-size(2rem, $fixture); + } + + @include expect { + font-size: 32px; + font-size: 2rem; + } + + } + + } + + @include it("can accommodate px numbers") { + + @include assert() { + + $fixture: ( + some-size: 16px, + ); + + @include output { + @include font-size(32px, $fixture); + } + + @include expect { + font-size: 32px; + font-size: 2rem; + } + + } + + } + @include it("errors if the argument does not resolve to a number") { + + @include assert() { + + $fixture: ( + some-key: (one, two, three, px), + ); + + @include output { + @include font-size(some-key, $fixture); + } + + @include expect { + _error: "Font size must be set using a 'px'-suffixed number or a 'rem'-suffixed number."; + } + + } + + } + + @include it("errors if the argument does not resolve to a 'px'-suffixed or 'rem'-suffixed number") { + + @include assert() { + + $fixture: ( + some-key: a-string-i-do-not-have-a-px-suffix-but-i-do-end-in-rem, + ); + + @include output { + @include font-size(some-key, $fixture); + } + + @include expect { + _error: "Font size must be set using a 'px'-suffixed number or a 'rem'-suffixed number."; + } + + } + + } +} + +@include describe("@mixin font-family") { + + @include it("sets the font family using the map's value when the argument is a map key") { + + @include assert() { + + $fixture: ( + some-font-family: '"Noto Sans", Arial, Helvetica, sans-serif', + ); + + @include output { + @include font-family(some-font-family, $fixture); + } + + @include expect { + font-family: "Noto Sans", Arial, Helvetica, sans-serif; + font-family: var(--font-some-font-family); + } + + } + + } + + @include it("errors when the argument is not a map key") { + + @include assert() { + + $fixture: (one: two); + + @include output { + @include font-family(non-existent-key, $fixture); + } + + @include expect { + _error: "Font family key `non-existent-key` not found in map"; + } + + } + + } + +} + +@include describe("@mixin label-content-typography") { + + @include it("Errors if the color argument supplied is not found in the color map") { + + @include assert() { + + $fixture: (some-key: some-value); + + @include output { + @include label-content-typography(not-a-color-map-key, true, $fixture); + } + + @include expect { + _error: "Can't resolve `not-a-color-map-key` in the color map"; + } + + } + + } + + @include it("Sets the color to be the value of the key in the color map if the color argument supplied is found in the color map") { + + @include assert() { + + $fixture: (some-color: red); + + @include output { + @include label-content-typography(some-color, true, $fixture); + } + + @include contains { + color: red; + } + + } + + } + +} + +@include describe("@mixin heading-level-typography") { + + $fixture-map: ( + size-h1: 10px, + size-h2: 20px, + size-h3: 30px, + size-h4: 40px, + size-h5: 50px, + size-h6: 60px, + // invalid heading size in order to verify the mixin doesn't use it + size-h7: 70px, + ); + $fixture-line-height: 24px; + + @include it("sets the h1 font size when supplied level 1") { + + @include assert() { + + @include output { + @include heading-level-typography(1, $fixture-line-height, $fixture-map); + } + + @include contains { + font-size: 10px; + font-size: var(--font-size-h1); + } + + } + + } + + @include it("sets the h1 font size when supplied level 2") { + + @include assert() { + + @include output { + @include heading-level-typography(2, $fixture-line-height, $fixture-map); + } + + @include contains { + font-size: 20px; + font-size: var(--font-size-h2); + } + + } + + } + + @include it("sets the h1 font size when supplied level 3") { + + @include assert() { + + @include output { + @include heading-level-typography(3, $fixture-line-height, $fixture-map); + } + + @include contains { + font-size: 30px; + font-size: var(--font-size-h3); + } + + } + + } + + @include it("sets the h1 font size when supplied level 4") { + + @include assert() { + + @include output { + @include heading-level-typography(4, $fixture-line-height, $fixture-map); + } + + @include contains { + font-size: 40px; + font-size: var(--font-size-h4); + } + + } + + } + + @include it("sets the h5 font size when supplied level 5") { + + @include assert() { + + @include output { + @include heading-level-typography(5, $fixture-line-height, $fixture-map); + } + + @include contains { + font-size: 50px; + font-size: var(--font-size-h5); + } + + } + + } + + @include it("sets the h6 font size when supplied level 6") { + + @include assert() { + + @include output { + @include heading-level-typography(6, $fixture-line-height, $fixture-map); + } + + @include contains { + font-size: 60px; + font-size: var(--font-size-h6); + } + + } + + } + + @include it("errors if supplied a heading level argument not between 1 and 6 inclusive") { + + @include assert() { + + @include output { + @include heading-level-typography(7, $fixture-line-height, $fixture-map); + } + + @include expect() { + _error: "Invalid heading level `7` supplied"; + } + + } + + } + + @include it("errors a valid headling level lacks a font size defninition in the map") { + + @include assert() { + + @include output { + @include heading-level-typography(1, $fixture-line-height, (size-h2: 20px)); + } + + @include expect() { + _error: "Font map is missing the definition of h1 font size"; + } + + } + + } + +} + +@include describe("@mixin set-font-size-and-vertical-height") { + + @include it("sets the font size when directly supplied") { + + @include assert() { + + @include output { + @include set-font-size-and-vertical-height(32px); + } + + @include contains { + font-size: 32px; + font-size: 2rem; + } + + } + + } + + @include it("sets the font size when supplied via the a map") { + + @include assert() { + + $fixture-map: (base-size: 16px); + $fixture-desired-height: 32px; + + @include output { + @include set-font-size-and-vertical-height(base-size, $fixture-desired-height, $fixture-map); + } + + @include contains { + font-size: 16px; + font-size: 1rem; + font-size: var(--font-base-size); + } + + } + + } + + @include it("correctly calculates the line height in order to obtain the supplied vertical height, taking into account the font size when supplied directly") { + + @include it("sets the font size when directly supplied") { + + @include assert() { + + @include output { + @include set-font-size-and-vertical-height(32px, 40px); + } + + @include contains { + line-height: 1.25; + } + + } + + } + + } + + @include it("correctly calculates the line height in order to obtain the supplied vertical height, taking into account the font size when supplied via a map") { + + @include assert() { + + $fixture-map: (base-size: 16px); + $fixture-desired-height: 32px; + + @include output { + @include set-font-size-and-vertical-height(base-size, $fixture-desired-height, $fixture-map); + } + + @include contains { + line-height: 2; + } + + } + + } + +} + @include describe("@mixin font-variant-position") { @include it("generates correct fallbacks with position 'sub'") {