diff --git a/.reuse/dep5 b/.reuse/dep5 index cc5da843da27..807a17e80a70 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -30,10 +30,6 @@ Copyright: 2020 SAP SE or an SAP affiliate company and OpenUI5 contributors License: Apache-2.0 -Files: packages/playground/assets/js/webcomponentsjs/* packages/ie11/src/thirdparty/Array.from.js packages/ie11/src/thirdparty/events-polyfills.js packages/ie11/src/thirdparty/Object.assign.js packages/ie11/src/thirdparty/template.js packages/ie11/src/thirdparty/webcomponents-sd-ce-pf.js -Copyright: 2018 The Polymer Project Authors -License: BSD-3-Clause-Clear - Files: packages/base/dist/sap/ui/thirdparty/caja-html-sanitizer.js Copyright: Google Inc. License: Apache-2.0 @@ -46,3 +42,11 @@ License: MIT Files: packages/playground/assets/js/vendor/lunr.min.js Copyright: 2017 Oliver Nightingale License: MIT + +Files: packages/tools/lib/copy-and-watch/index.js +Copyright: 2017 Aleksandr Zonov +License: MIT + +Files: packages/tools/lib/postcss-combine-duplicated-selectors/index.js +Copyright: 2016 Christian Murphy +License: MIT diff --git a/packages/base/hash.txt b/packages/base/hash.txt index c45c26c9db98..0d33b3a220ab 100644 --- a/packages/base/hash.txt +++ b/packages/base/hash.txt @@ -1 +1 @@ -X8vjgfCUlDRvJz9L9e5OzLqCCdQ= \ No newline at end of file +owW4JG1/w/h6BH4GK+Akd5v6xzc= \ No newline at end of file diff --git a/packages/theming/config/postcss.themes/postcss.config.js b/packages/theming/config/postcss.themes/postcss.config.js index 4d19e9b435a3..2d0c547c5f90 100644 --- a/packages/theming/config/postcss.themes/postcss.config.js +++ b/packages/theming/config/postcss.themes/postcss.config.js @@ -1,4 +1,4 @@ -const combineSelectors = require('postcss-combine-duplicated-selectors'); +const combineSelectors = require('@ui5/webcomponents-tools/lib/postcss-combine-duplicated-selectors/index.js'); const postcssImport = require('postcss-import'); const cssnano = require('cssnano'); const postcssCSStoJSON = require('@ui5/webcomponents-tools/lib/postcss-css-to-json/index.js'); diff --git a/packages/theming/package.json b/packages/theming/package.json index a46bc2371105..176522635948 100644 --- a/packages/theming/package.json +++ b/packages/theming/package.json @@ -40,7 +40,6 @@ "json-beautify": "^1.1.1", "nps": "^5.10.0", "postcss": "^8.4.5", - "postcss-combine-duplicated-selectors": "^10.0.3", "postcss-import": "^14.0.2", "resolve": "^1.20.0" }, diff --git a/packages/tools/components-package/postcss.themes.js b/packages/tools/components-package/postcss.themes.js index 4cfcb2e472fb..a89f25d177a7 100644 --- a/packages/tools/components-package/postcss.themes.js +++ b/packages/tools/components-package/postcss.themes.js @@ -1,5 +1,5 @@ const postcssImport = require('postcss-import'); -const combineSelectors = require('postcss-combine-duplicated-selectors'); +const combineSelectors = require('../lib/postcss-combine-duplicated-selectors/index.js'); const postcssCSStoJSON = require('../lib/postcss-css-to-json/index.js'); const postcssCSStoESM = require('../lib/postcss-css-to-esm/index.js'); const cssnano = require('cssnano'); diff --git a/packages/tools/lib/copy-and-watch/index.js b/packages/tools/lib/copy-and-watch/index.js index b4f054adeb91..710d3aff1d17 100644 --- a/packages/tools/lib/copy-and-watch/index.js +++ b/packages/tools/lib/copy-and-watch/index.js @@ -1,3 +1,27 @@ +/* +MIT License + +Copyright (c) 2017 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + const fs = require('fs'); const path = require('path'); const chokidar = require('chokidar'); diff --git a/packages/tools/lib/postcss-combine-duplicated-selectors/index.js b/packages/tools/lib/postcss-combine-duplicated-selectors/index.js new file mode 100644 index 000000000000..c337b08d2eb5 --- /dev/null +++ b/packages/tools/lib/postcss-combine-duplicated-selectors/index.js @@ -0,0 +1,178 @@ +/* + The MIT License (MIT) + +Copyright (c) 2016 Christian Murphy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +const parser = require('postcss-selector-parser'); +const name = "postcss-combine-duplicated-selectors"; + +/** + * Ensure that attributes with different quotes match. + * @param {Object} selector - postcss selector node + */ +function normalizeAttributes(selector) { + selector.walkAttributes((node) => { + if (node.value) { + // remove quotes + node.value = node.value.replace(/'|\\'|"|\\"/g, ''); + } + }); +} + +/** + * Sort class and id groups alphabetically + * @param {Object} selector - postcss selector node + */ +function sortGroups(selector) { + selector.each((subSelector) => { + subSelector.nodes.sort((a, b) => { + // different types cannot be sorted + if (a.type !== b.type) { + return 0; + } + + // sort alphabetically + return a.value < b.value ? -1 : 1; + }); + }); + + selector.sort((a, b) => (a.nodes.join('') < b.nodes.join('') ? -1 : 1)); +} + +/** + * Remove duplicated properties + * @param {Object} selector - postcss selector node + * @param {Boolean} exact + */ +function removeDupProperties(selector, exact) { + if (!exact) { // Remove duplicated properties, regardless of value + const retainedProps = new Set(); + + for (let actIndex = selector.nodes.length - 1; actIndex >= 1; actIndex--) { + const prop = selector.nodes[actIndex].prop; + if (prop !== undefined) { + if (!retainedProps.has(prop)) { + retainedProps.add(prop); // Mark the prop as retained, all other occurrences must be removed + } else { + selector.nodes[actIndex].remove(); // This occurrence of the prop must be removed + } + } + } + } else { + // Remove duplicated properties from bottom to top () + for (let actIndex = selector.nodes.length - 1; actIndex >= 1; actIndex--) { + for (let befIndex = actIndex - 1; befIndex >= 0; befIndex--) { + if ( + selector.nodes[actIndex].prop === selector.nodes[befIndex].prop && + selector.nodes[actIndex].value === selector.nodes[befIndex].value + ) { + selector.nodes[befIndex].remove(); + actIndex--; + } + } + } + } +} + +const uniformStyle = parser((selector) => { + normalizeAttributes(selector); + sortGroups(selector); +}); + +const defaultOptions = { + removeDuplicatedProperties: false, +}; + +module.exports = (options) => { + options = Object.assign({}, defaultOptions, options); + return { + postcssPlugin: name, + prepare() { + // Create a map to store maps + const mapTable = new Map(); + // root map to store root selectors + mapTable.set('root', new Map()); + + return { + Rule: (rule) => { + let map; + // Check selector parent for any at rule + if (rule.parent.type === 'atrule') { + // Use name and query params as the key + const query = + rule.parent.name.toLowerCase() + + rule.parent.params.replace(/\s+/g, ''); + + // See if this query key is already in the map table + map = mapTable.has(query) ? // If it is use it + mapTable.get(query) : // if not set it and get it + mapTable.set(query, new Map()).get(query); + } else { + // Otherwise we are dealing with a selector in the root + map = mapTable.get('root'); + } + + // create a uniform selector + const selector = uniformStyle.processSync(rule.selector, { + lossless: false, + }); + + if (map.has(selector)) { + // store original rule as destination + const destination = map.get(selector); + + // check if node has already been processed + if (destination === rule) return; + + // move declarations to original rule + while (rule.nodes.length > 0) { + destination.append(rule.nodes[0]); + } + // remove duplicated rule + rule.remove(); + + if ( + options.removeDuplicatedProperties || + options.removeDuplicatedValues + ) { + removeDupProperties( + destination, + options.removeDuplicatedValues, + ); + } + } else { + if ( + options.removeDuplicatedProperties || + options.removeDuplicatedValues + ) { + removeDupProperties(rule, options.removeDuplicatedValues); + } + // add new selector to symbol table + map.set(selector, rule); + } + }, + }; + }, + }; +}; + +module.exports.postcss = true; diff --git a/packages/tools/package.json b/packages/tools/package.json index ba771802bdde..f86ddd63e1ff 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -56,8 +56,8 @@ "nps": "^5.10.0", "postcss": "^8.4.5", "postcss-cli": "^9.1.0", - "postcss-combine-duplicated-selectors": "^10.0.3", "postcss-import": "^14.0.2", + "postcss-selector-parser": "^6.0.10", "properties-reader": "^2.2.0", "recursive-readdir": "^2.2.2", "resolve": "^1.20.0", diff --git a/yarn.lock b/yarn.lock index 372bea452da6..7fd804881367 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5611,13 +5611,6 @@ postcss-colormin@^4.0.3: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-combine-duplicated-selectors@^10.0.3: - version "10.0.3" - resolved "https://registry.yarnpkg.com/postcss-combine-duplicated-selectors/-/postcss-combine-duplicated-selectors-10.0.3.tgz#71e8b6783e99cd560cf08ba7b896ad0db318c11c" - integrity sha512-IP0BmwFloCskv7DV7xqvzDXqMHpwdczJa6ZvIW8abgHdcIHs9mCJX2ltFhu3EwA51ozp13DByng30+Ke+eIExA== - dependencies: - postcss-selector-parser "^6.0.4" - postcss-convert-values@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" @@ -5860,7 +5853,15 @@ postcss-selector-parser@^3.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: +postcss-selector-parser@^6.0.10: + version "6.0.10" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" + integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-selector-parser@^6.0.2: version "6.0.9" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==