diff --git a/src/node_modules/postcss-custom-media/CHANGELOG.md b/src/node_modules/postcss-custom-media/CHANGELOG.md new file mode 100755 index 0000000..8f3d988 --- /dev/null +++ b/src/node_modules/postcss-custom-media/CHANGELOG.md @@ -0,0 +1,108 @@ +# Changes to PostCSS Custom Media + +### 8.0.0 (January 12, 2021) + +- Added: Support for PostCSS v8 + +### 7.0.8 (March 30, 2019) + +- Fixed: Issue importing from `.pcss` files +- Updated: `postcss` to 7.0.14 (patch) + +### 7.0.7 (October 19, 2018) + +- Fixed: Issue combining custom media media queries with `and` + +### 7.0.6 (October 12, 2018) + +- Fixed: Issue combining multiple custom media + +### 7.0.5 (October 5, 2018) + +- Fixed: Possible issues resolving paths to imports and exports +- Added: Imports from `customMedia` and `custom-media` simultaneously +- Updated: `postcss` to 7.0.5 + +### 7.0.4 (September 23, 2018) + +- Added: `importFromPlugins` option to process imports + +### 7.0.3 (September 20, 2018) + +- Fixed: Do not break on an empty `importFrom` object + +### 7.0.2 (September 15, 2018) + +- Fixed: An issue with re-assigning params as a non-string + +### 7.0.1 (September 14, 2018) + +- Fixed: An issue with how opposing queries are resolved. + +### 7.0.0 (September 14, 2018) + +- Added: New `preserve` option to preserve custom media and atrules using them +- Added: New `exportTo` function to specify where to export custom media +- Added: New `importFrom` option to specify where to import custom media +- Added: Support for PostCSS v7 +- Added: Support for Node v6+ + +# 6.0.0 (May 12, 2017) + +- Added: compatibility with postcss v6.x + +# 5.0.1 (February 3, 2016) + +- Fixed: circular dependencies are properly detected +([#17](https://github.com/postcss/postcss-custom-media/pull/17)) + +# 5.0.0 (August 25, 2015) + +- Removed: compatibility with postcss v4.x +- Added: compatibility with postcss v5.x + +# 4.1.0 (06 30, 2015) + +- Added: Allow custom media to reference each other +([#10](https://github.com/postcss/postcss-custom-media/pull/10)) + +# 4.0.0 (May 17, 2015) + +- Changed: warning messages are now sent via postcss messages api (^4.1.0) +- Added: automatic custom media `--` prefixing +([#11](https://github.com/postcss/postcss-custom-media/issues/11)) +- Added: `preserve` allows you to preserve custom media query defintions +- Added: `appendExtensions` allows you (when `preserve` is truthy) to append your extensions as media queries + +# 3.0.0 (January 29, 2015) + +- Added: compatibility with postcss v4.x +- Removed: compatibility with postcss v3.x + +# 2.0.0 [Yanked] + +_You never saw this version (this is a bad release that points to 1.0.0)._ + +# 1.3.0 (November 25, 2014) + +- Changed: better gnu message + +# 1.2.1 (October 9, 2014) + +- Fixed: npm description + +# 1.2.0 (October 1, 2014) + +- Added: support for multiples media in query list (ref [#rework-custom-media/5](https://github.com/reworkcss/rework-custom-media/pull/5)) + +# 1.1.0 (September 30, 2014) + +- Added: support for js-defined media queries (fix [#3](https://github.com/postcss/postcss-custom-media/issues/3)) + +# 1.0.1 (September 16, 2014) + +- Added: Allow whitespace around custom media name (fix [#2](https://github.com/postcss/postcss-custom-media/issues/2)) + +# 1.0.0 (August 12, 2014) + +✨ First release based on [rework-custom-media](https://github.com/reworkcss/rework-custom-media) v0.1.1 diff --git a/src/node_modules/postcss-custom-media/LICENSE.md b/src/node_modules/postcss-custom-media/LICENSE.md new file mode 100644 index 0000000..6d70470 --- /dev/null +++ b/src/node_modules/postcss-custom-media/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +Copyright © PostCSS + +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. diff --git a/src/node_modules/postcss-custom-media/README.md b/src/node_modules/postcss-custom-media/README.md new file mode 100755 index 0000000..12a145e --- /dev/null +++ b/src/node_modules/postcss-custom-media/README.md @@ -0,0 +1,178 @@ +# PostCSS Custom Media [PostCSS][postcss] + +[![NPM Version][npm-img]][npm-url] +[![CSS Standard Status][css-img]][css-url] +[![Build Status][cli-img]][cli-url] +[![Support Chat][git-img]][git-url] + +[PostCSS Custom Media] lets you use Custom Media Queries in CSS, following the +[CSS Media Queries] specification. + +```pcss +@custom-media --small-viewport (max-width: 30em); + +@media (--small-viewport) { + /* styles for small viewport */ +} + +/* becomes */ + +@media (max-width: 30em) { + /* styles for small viewport */ +} +``` + +## Usage + +Add [PostCSS Custom Media] to your project: + +```bash +npm install postcss-custom-media --save-dev +``` + +Use [PostCSS Custom Media] to process your CSS: + +```js +const postcssCustomMedia = require('postcss-custom-media'); + +postcssCustomMedia.process(YOUR_CSS /*, processOptions, pluginOptions */); +``` + +Or use it as a [PostCSS] plugin: + +```js +const postcss = require('postcss'); +const postcssCustomMedia = require('postcss-custom-media'); + +postcss([ + postcssCustomMedia(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +[PostCSS Custom Media] runs in all Node environments, with special instructions for: + +| [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Create React App](INSTALL.md#create-react-app) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) | +| --- | --- | --- | --- | --- | --- | + +## Options + +### preserve + +The `preserve` option determines whether custom media and atrules using custom +media should be preserved in their original form. + +```pcss +@custom-media --small-viewport (max-width: 30em); + +@media (--small-viewport) { + /* styles for small viewport */ +} + +/* becomes */ + +@custom-media --small-viewport (max-width: 30em); + +@media (max-width: 30em) { + /* styles for small viewport */ +} + +@media (--small-viewport) { + /* styles for small viewport */ +} +``` + +### importFrom + +The `importFrom` option specifies sources where custom media can be imported +from, which might be CSS, JS, and JSON files, functions, and directly passed +objects. + +```js +postcssCustomMedia({ + importFrom: 'path/to/file.css' // => @custom-selector --small-viewport (max-width: 30em); +}); +``` + +```pcss +@media (max-width: 30em) { + /* styles for small viewport */ +} + +@media (--small-viewport) { + /* styles for small viewport */ +} +``` + +Multiple sources can be passed into this option, and they will be parsed in the +order they are received. JavaScript files, JSON files, functions, and objects +will need to namespace custom media using the `customMedia` or +`custom-media` key. + +```js +postcssCustomMedia({ + importFrom: [ + 'path/to/file.css', + 'and/then/this.js', + 'and/then/that.json', + { + customMedia: { '--small-viewport': '(max-width: 30em)' } + }, + () => { + const customMedia = { '--small-viewport': '(max-width: 30em)' }; + + return { customMedia }; + } + ] +}); +``` + +### exportTo + +The `exportTo` option specifies destinations where custom media can be exported +to, which might be CSS, JS, and JSON files, functions, and directly passed +objects. + +```js +postcssCustomMedia({ + exportTo: 'path/to/file.css' // @custom-media --small-viewport (max-width: 30em); +}); +``` + +Multiple destinations can be passed into this option, and they will be parsed +in the order they are received. JavaScript files, JSON files, and objects will +need to namespace custom media using the `customMedia` or +`custom-media` key. + +```js +const cachedObject = { customMedia: {} }; + +postcssCustomMedia({ + exportTo: [ + 'path/to/file.css', // @custom-media --small-viewport (max-width: 30em); + 'and/then/this.js', // module.exports = { customMedia: { '--small-viewport': '(max-width: 30em)' } } + 'and/then/this.mjs', // export const customMedia = { '--small-viewport': '(max-width: 30em)' } } + 'and/then/that.json', // { "custom-media": { "--small-viewport": "(max-width: 30em)" } } + cachedObject, + customMedia => { + customMedia // { '--small-viewport': '(max-width: 30em)' } + } + ] +}); +``` + +See example exports written to [CSS](test/export-media.css), +[JS](test/export-media.js), [MJS](test/export-media.mjs), and +[JSON](test/export-media.json). + +[cli-img]: https://img.shields.io/travis/postcss/postcss-custom-media/master.svg +[cli-url]: https://travis-ci.org/postcss/postcss-custom-media +[css-img]: https://cssdb.org/badge/custom-media-queries.svg +[css-url]: https://cssdb.org/#custom-media-queries +[git-img]: https://img.shields.io/badge/support-chat-blue.svg +[git-url]: https://gitter.im/postcss/postcss +[npm-img]: https://img.shields.io/npm/v/postcss-custom-media.svg +[npm-url]: https://www.npmjs.com/package/postcss-custom-media + +[CSS Media Queries]: https://drafts.csswg.org/mediaqueries-5/#custom-mq +[PostCSS]: https://github.com/postcss/postcss +[PostCSS Custom Media]: https://github.com/postcss/postcss-custom-media diff --git a/src/node_modules/postcss-custom-media/index.cjs.js b/src/node_modules/postcss-custom-media/index.cjs.js new file mode 100644 index 0000000..7cf719e --- /dev/null +++ b/src/node_modules/postcss-custom-media/index.cjs.js @@ -0,0 +1,557 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var postcss = require('postcss'); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +function _interopNamespace(e) { + if (e && e.__esModule) return e; + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== 'default') { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { + return e[k]; + } + }); + } + }); + } + n['default'] = e; + return Object.freeze(n); +} + +var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); +var path__default = /*#__PURE__*/_interopDefaultLegacy(path); + +function parse(string, splitByAnd) { + const array = []; + let buffer = ''; + let split = false; + let func = 0; + let i = -1; + + while (++i < string.length) { + const char = string[i]; + + if (char === '(') { + func += 1; + } else if (char === ')') { + if (func > 0) { + func -= 1; + } + } else if (func === 0) { + if (splitByAnd && andRegExp.test(buffer + char)) { + split = true; + } else if (!splitByAnd && char === ',') { + split = true; + } + } + + if (split) { + array.push(splitByAnd ? new MediaExpression(buffer + char) : new MediaQuery(buffer)); + buffer = ''; + split = false; + } else { + buffer += char; + } + } + + if (buffer !== '') { + array.push(splitByAnd ? new MediaExpression(buffer) : new MediaQuery(buffer)); + } + + return array; +} + +class MediaQueryList { + constructor(string) { + this.nodes = parse(string); + } + + invert() { + this.nodes.forEach(node => { + node.invert(); + }); + return this; + } + + clone() { + return new MediaQueryList(String(this)); + } + + toString() { + return this.nodes.join(','); + } + +} + +class MediaQuery { + constructor(string) { + const [, before, media, after] = string.match(spaceWrapRegExp); + const [, modifier = '', afterModifier = ' ', type = '', beforeAnd = '', and = '', beforeExpression = '', expression1 = '', expression2 = ''] = media.match(mediaRegExp) || []; + const raws = { + before, + after, + afterModifier, + originalModifier: modifier || '', + beforeAnd, + and, + beforeExpression + }; + const nodes = parse(expression1 || expression2, true); + Object.assign(this, { + modifier, + type, + raws, + nodes + }); + } + + clone(overrides) { + const instance = new MediaQuery(String(this)); + Object.assign(instance, overrides); + return instance; + } + + invert() { + this.modifier = this.modifier ? '' : this.raws.originalModifier; + return this; + } + + toString() { + const { + raws + } = this; + return `${raws.before}${this.modifier}${this.modifier ? `${raws.afterModifier}` : ''}${this.type}${raws.beforeAnd}${raws.and}${raws.beforeExpression}${this.nodes.join('')}${this.raws.after}`; + } + +} + +class MediaExpression { + constructor(string) { + const [, value, after = '', and = '', afterAnd = ''] = string.match(andRegExp) || [null, string]; + const raws = { + after, + and, + afterAnd + }; + Object.assign(this, { + value, + raws + }); + } + + clone(overrides) { + const instance = new MediaExpression(String(this)); + Object.assign(instance, overrides); + return instance; + } + + toString() { + const { + raws + } = this; + return `${this.value}${raws.after}${raws.and}${raws.afterAnd}`; + } + +} + +const modifierRE = '(not|only)'; +const typeRE = '(all|print|screen|speech)'; +const noExpressionRE = '([\\W\\w]*)'; +const expressionRE = '([\\W\\w]+)'; +const noSpaceRE = '(\\s*)'; +const spaceRE = '(\\s+)'; +const andRE = '(?:(\\s+)(and))'; +const andRegExp = new RegExp(`^${expressionRE}(?:${andRE}${spaceRE})$`, 'i'); +const spaceWrapRegExp = new RegExp(`^${noSpaceRE}${noExpressionRE}${noSpaceRE}$`); +const mediaRegExp = new RegExp(`^(?:${modifierRE}${spaceRE})?(?:${typeRE}(?:${andRE}${spaceRE}${expressionRE})?|${expressionRE})$`, 'i'); +var mediaASTFromString = (string => new MediaQueryList(string)); + +var getCustomMediaFromRoot = ((root, opts) => { + // initialize custom selectors + const customMedias = {}; // for each custom selector atrule that is a child of the css root + + root.nodes.slice().forEach(node => { + if (isCustomMedia(node)) { + // extract the name and selectors from the params of the custom selector + const [, name, selectors] = node.params.match(customMediaParamsRegExp); // write the parsed selectors to the custom selector + + customMedias[name] = mediaASTFromString(selectors); // conditionally remove the custom selector atrule + + if (!Object(opts).preserve) { + node.remove(); + } + } + }); + return customMedias; +}); // match the custom selector name + +const customMediaNameRegExp = /^custom-media$/i; // match the custom selector params + +const customMediaParamsRegExp = /^(--[A-z][\w-]*)\s+([\W\w]+)\s*$/; // whether the atrule is a custom selector + +const isCustomMedia = node => node.type === 'atrule' && customMediaNameRegExp.test(node.name) && customMediaParamsRegExp.test(node.params); + +/* Get Custom Media from CSS File +/* ========================================================================== */ + +async function getCustomMediaFromCSSFile(from) { + const css = await readFile(from); + const root = postcss.parse(css, { + from + }); + return getCustomMediaFromRoot(root, { + preserve: true + }); +} +/* Get Custom Media from Object +/* ========================================================================== */ + + +function getCustomMediaFromObject(object) { + const customMedia = Object.assign({}, Object(object).customMedia, Object(object)['custom-media']); + + for (const key in customMedia) { + customMedia[key] = mediaASTFromString(customMedia[key]); + } + + return customMedia; +} +/* Get Custom Media from JSON file +/* ========================================================================== */ + + +async function getCustomMediaFromJSONFile(from) { + const object = await readJSON(from); + return getCustomMediaFromObject(object); +} +/* Get Custom Media from JS file +/* ========================================================================== */ + + +async function getCustomMediaFromJSFile(from) { + const object = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require(from)); }); + return getCustomMediaFromObject(object); +} +/* Get Custom Media from Sources +/* ========================================================================== */ + + +function getCustomMediaFromSources(sources) { + return sources.map(source => { + if (source instanceof Promise) { + return source; + } else if (source instanceof Function) { + return source(); + } // read the source as an object + + + const opts = source === Object(source) ? source : { + from: String(source) + }; // skip objects with custom media + + if (Object(opts).customMedia || Object(opts)['custom-media']) { + return opts; + } // source pathname + + + const from = path__default['default'].resolve(String(opts.from || '')); // type of file being read from + + const type = (opts.type || path__default['default'].extname(from).slice(1)).toLowerCase(); + return { + type, + from + }; + }).reduce(async (customMedia, source) => { + const { + type, + from + } = await source; + + if (type === 'css' || type === 'pcss') { + return Object.assign(await customMedia, await getCustomMediaFromCSSFile(from)); + } + + if (type === 'js') { + return Object.assign(await customMedia, await getCustomMediaFromJSFile(from)); + } + + if (type === 'json') { + return Object.assign(await customMedia, await getCustomMediaFromJSONFile(from)); + } + + return Object.assign(await customMedia, getCustomMediaFromObject(await source)); + }, {}); +} +/* Helper utilities +/* ========================================================================== */ + +const readFile = from => new Promise((resolve, reject) => { + fs__default['default'].readFile(from, 'utf8', (error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }); +}); + +const readJSON = async from => JSON.parse(await readFile(from)); + +// return transformed medias, replacing custom pseudo medias with custom medias +function transformMediaList(mediaList, customMedias) { + let index = mediaList.nodes.length - 1; + + while (index >= 0) { + const transformedMedias = transformMedia(mediaList.nodes[index], customMedias); + + if (transformedMedias.length) { + mediaList.nodes.splice(index, 1, ...transformedMedias); + } + + --index; + } + + return mediaList; +} // return custom pseudo medias replaced with custom medias + +function transformMedia(media, customMedias) { + const transpiledMedias = []; + + for (const index in media.nodes) { + const { + value, + nodes + } = media.nodes[index]; + const key = value.replace(customPseudoRegExp, '$1'); + + if (key in customMedias) { + for (const replacementMedia of customMedias[key].nodes) { + // use the first available modifier unless they cancel each other out + const modifier = media.modifier !== replacementMedia.modifier ? media.modifier || replacementMedia.modifier : ''; + const mediaClone = media.clone({ + modifier, + // conditionally use the raws from the first available modifier + raws: !modifier || media.modifier ? { ...media.raws + } : { ...replacementMedia.raws + }, + type: media.type || replacementMedia.type + }); // conditionally include more replacement raws when the type is present + + if (mediaClone.type === replacementMedia.type) { + Object.assign(mediaClone.raws, { + and: replacementMedia.raws.and, + beforeAnd: replacementMedia.raws.beforeAnd, + beforeExpression: replacementMedia.raws.beforeExpression + }); + } + + mediaClone.nodes.splice(index, 1, ...replacementMedia.clone().nodes.map(node => { + // use raws and spacing from the current usage + if (media.nodes[index].raws.and) { + node.raws = { ...media.nodes[index].raws + }; + } + + node.spaces = { ...media.nodes[index].spaces + }; + return node; + })); // remove the currently transformed key to prevent recursion + + const nextCustomMedia = getCustomMediasWithoutKey(customMedias, key); + const retranspiledMedias = transformMedia(mediaClone, nextCustomMedia); + + if (retranspiledMedias.length) { + transpiledMedias.push(...retranspiledMedias); + } else { + transpiledMedias.push(mediaClone); + } + } + + return transpiledMedias; + } else if (nodes && nodes.length) { + transformMediaList(media.nodes[index], customMedias); + } + } + + return transpiledMedias; +} + +const customPseudoRegExp = /\((--[A-z][\w-]*)\)/; + +const getCustomMediasWithoutKey = (customMedias, key) => { + const nextCustomMedias = Object.assign({}, customMedias); + delete nextCustomMedias[key]; + return nextCustomMedias; +}; + +var transformAtrules = ((root, customMedia, opts) => { + root.walkAtRules(mediaAtRuleRegExp, atrule => { + if (customPseudoRegExp$1.test(atrule.params)) { + const mediaAST = mediaASTFromString(atrule.params); + const params = String(transformMediaList(mediaAST, customMedia)); + + if (opts.preserve) { + atrule.cloneBefore({ + params + }); + } else { + atrule.params = params; + } + } + }); +}); +const mediaAtRuleRegExp = /^media$/i; +const customPseudoRegExp$1 = /\(--[A-z][\w-]*\)/; + +/* Write Custom Media from CSS File +/* ========================================================================== */ + +async function writeCustomMediaToCssFile(to, customMedia) { + const cssContent = Object.keys(customMedia).reduce((cssLines, name) => { + cssLines.push(`@custom-media ${name} ${customMedia[name]};`); + return cssLines; + }, []).join('\n'); + const css = `${cssContent}\n`; + await writeFile(to, css); +} +/* Write Custom Media from JSON file +/* ========================================================================== */ + + +async function writeCustomMediaToJsonFile(to, customMedia) { + const jsonContent = JSON.stringify({ + 'custom-media': customMedia + }, null, ' '); + const json = `${jsonContent}\n`; + await writeFile(to, json); +} +/* Write Custom Media from Common JS file +/* ========================================================================== */ + + +async function writeCustomMediaToCjsFile(to, customMedia) { + const jsContents = Object.keys(customMedia).reduce((jsLines, name) => { + jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(customMedia[name])}'`); + return jsLines; + }, []).join(',\n'); + const js = `module.exports = {\n\tcustomMedia: {\n${jsContents}\n\t}\n};\n`; + await writeFile(to, js); +} +/* Write Custom Media from Module JS file +/* ========================================================================== */ + + +async function writeCustomMediaToMjsFile(to, customMedia) { + const mjsContents = Object.keys(customMedia).reduce((mjsLines, name) => { + mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(customMedia[name])}'`); + return mjsLines; + }, []).join(',\n'); + const mjs = `export const customMedia = {\n${mjsContents}\n};\n`; + await writeFile(to, mjs); +} +/* Write Custom Media to Exports +/* ========================================================================== */ + + +function writeCustomMediaToExports(customMedia, destinations) { + return Promise.all(destinations.map(async destination => { + if (destination instanceof Function) { + await destination(defaultCustomMediaToJSON(customMedia)); + } else { + // read the destination as an object + const opts = destination === Object(destination) ? destination : { + to: String(destination) + }; // transformer for custom media into a JSON-compatible object + + const toJSON = opts.toJSON || defaultCustomMediaToJSON; + + if ('customMedia' in opts) { + // write directly to an object as customMedia + opts.customMedia = toJSON(customMedia); + } else if ('custom-media' in opts) { + // write directly to an object as custom-media + opts['custom-media'] = toJSON(customMedia); + } else { + // destination pathname + const to = String(opts.to || ''); // type of file being written to + + const type = (opts.type || path__default['default'].extname(to).slice(1)).toLowerCase(); // transformed custom media + + const customMediaJSON = toJSON(customMedia); + + if (type === 'css') { + await writeCustomMediaToCssFile(to, customMediaJSON); + } + + if (type === 'js') { + await writeCustomMediaToCjsFile(to, customMediaJSON); + } + + if (type === 'json') { + await writeCustomMediaToJsonFile(to, customMediaJSON); + } + + if (type === 'mjs') { + await writeCustomMediaToMjsFile(to, customMediaJSON); + } + } + } + })); +} +/* Helper utilities +/* ========================================================================== */ + +const defaultCustomMediaToJSON = customMedia => { + return Object.keys(customMedia).reduce((customMediaJSON, key) => { + customMediaJSON[key] = String(customMedia[key]); + return customMediaJSON; + }, {}); +}; + +const writeFile = (to, text) => new Promise((resolve, reject) => { + fs__default['default'].writeFile(to, text, error => { + if (error) { + reject(error); + } else { + resolve(); + } + }); +}); + +const escapeForJS = string => string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r'); + +const creator = opts => { + // whether to preserve custom media and at-rules using them + const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : false; // sources to import custom media from + + const importFrom = [].concat(Object(opts).importFrom || []); // destinations to export custom media to + + const exportTo = [].concat(Object(opts).exportTo || []); // promise any custom media are imported + + const customMediaPromise = getCustomMediaFromSources(importFrom); + return { + postcssPlugin: 'postcss-custom-media', + Once: async root => { + const customMedia = Object.assign(await customMediaPromise, getCustomMediaFromRoot(root, { + preserve + })); + await writeCustomMediaToExports(customMedia, exportTo); + transformAtrules(root, customMedia, { + preserve + }); + } + }; +}; + +creator.postcss = true; + +module.exports = creator; +//# sourceMappingURL=index.cjs.js.map diff --git a/src/node_modules/postcss-custom-media/index.es.mjs b/src/node_modules/postcss-custom-media/index.es.mjs new file mode 100644 index 0000000..e109c9f --- /dev/null +++ b/src/node_modules/postcss-custom-media/index.es.mjs @@ -0,0 +1,530 @@ +import fs from 'fs'; +import path from 'path'; +import { parse as parse$1 } from 'postcss'; + +function parse(string, splitByAnd) { + const array = []; + let buffer = ''; + let split = false; + let func = 0; + let i = -1; + + while (++i < string.length) { + const char = string[i]; + + if (char === '(') { + func += 1; + } else if (char === ')') { + if (func > 0) { + func -= 1; + } + } else if (func === 0) { + if (splitByAnd && andRegExp.test(buffer + char)) { + split = true; + } else if (!splitByAnd && char === ',') { + split = true; + } + } + + if (split) { + array.push(splitByAnd ? new MediaExpression(buffer + char) : new MediaQuery(buffer)); + buffer = ''; + split = false; + } else { + buffer += char; + } + } + + if (buffer !== '') { + array.push(splitByAnd ? new MediaExpression(buffer) : new MediaQuery(buffer)); + } + + return array; +} + +class MediaQueryList { + constructor(string) { + this.nodes = parse(string); + } + + invert() { + this.nodes.forEach(node => { + node.invert(); + }); + return this; + } + + clone() { + return new MediaQueryList(String(this)); + } + + toString() { + return this.nodes.join(','); + } + +} + +class MediaQuery { + constructor(string) { + const [, before, media, after] = string.match(spaceWrapRegExp); + const [, modifier = '', afterModifier = ' ', type = '', beforeAnd = '', and = '', beforeExpression = '', expression1 = '', expression2 = ''] = media.match(mediaRegExp) || []; + const raws = { + before, + after, + afterModifier, + originalModifier: modifier || '', + beforeAnd, + and, + beforeExpression + }; + const nodes = parse(expression1 || expression2, true); + Object.assign(this, { + modifier, + type, + raws, + nodes + }); + } + + clone(overrides) { + const instance = new MediaQuery(String(this)); + Object.assign(instance, overrides); + return instance; + } + + invert() { + this.modifier = this.modifier ? '' : this.raws.originalModifier; + return this; + } + + toString() { + const { + raws + } = this; + return `${raws.before}${this.modifier}${this.modifier ? `${raws.afterModifier}` : ''}${this.type}${raws.beforeAnd}${raws.and}${raws.beforeExpression}${this.nodes.join('')}${this.raws.after}`; + } + +} + +class MediaExpression { + constructor(string) { + const [, value, after = '', and = '', afterAnd = ''] = string.match(andRegExp) || [null, string]; + const raws = { + after, + and, + afterAnd + }; + Object.assign(this, { + value, + raws + }); + } + + clone(overrides) { + const instance = new MediaExpression(String(this)); + Object.assign(instance, overrides); + return instance; + } + + toString() { + const { + raws + } = this; + return `${this.value}${raws.after}${raws.and}${raws.afterAnd}`; + } + +} + +const modifierRE = '(not|only)'; +const typeRE = '(all|print|screen|speech)'; +const noExpressionRE = '([\\W\\w]*)'; +const expressionRE = '([\\W\\w]+)'; +const noSpaceRE = '(\\s*)'; +const spaceRE = '(\\s+)'; +const andRE = '(?:(\\s+)(and))'; +const andRegExp = new RegExp(`^${expressionRE}(?:${andRE}${spaceRE})$`, 'i'); +const spaceWrapRegExp = new RegExp(`^${noSpaceRE}${noExpressionRE}${noSpaceRE}$`); +const mediaRegExp = new RegExp(`^(?:${modifierRE}${spaceRE})?(?:${typeRE}(?:${andRE}${spaceRE}${expressionRE})?|${expressionRE})$`, 'i'); +var mediaASTFromString = (string => new MediaQueryList(string)); + +var getCustomMediaFromRoot = ((root, opts) => { + // initialize custom selectors + const customMedias = {}; // for each custom selector atrule that is a child of the css root + + root.nodes.slice().forEach(node => { + if (isCustomMedia(node)) { + // extract the name and selectors from the params of the custom selector + const [, name, selectors] = node.params.match(customMediaParamsRegExp); // write the parsed selectors to the custom selector + + customMedias[name] = mediaASTFromString(selectors); // conditionally remove the custom selector atrule + + if (!Object(opts).preserve) { + node.remove(); + } + } + }); + return customMedias; +}); // match the custom selector name + +const customMediaNameRegExp = /^custom-media$/i; // match the custom selector params + +const customMediaParamsRegExp = /^(--[A-z][\w-]*)\s+([\W\w]+)\s*$/; // whether the atrule is a custom selector + +const isCustomMedia = node => node.type === 'atrule' && customMediaNameRegExp.test(node.name) && customMediaParamsRegExp.test(node.params); + +/* Get Custom Media from CSS File +/* ========================================================================== */ + +async function getCustomMediaFromCSSFile(from) { + const css = await readFile(from); + const root = parse$1(css, { + from + }); + return getCustomMediaFromRoot(root, { + preserve: true + }); +} +/* Get Custom Media from Object +/* ========================================================================== */ + + +function getCustomMediaFromObject(object) { + const customMedia = Object.assign({}, Object(object).customMedia, Object(object)['custom-media']); + + for (const key in customMedia) { + customMedia[key] = mediaASTFromString(customMedia[key]); + } + + return customMedia; +} +/* Get Custom Media from JSON file +/* ========================================================================== */ + + +async function getCustomMediaFromJSONFile(from) { + const object = await readJSON(from); + return getCustomMediaFromObject(object); +} +/* Get Custom Media from JS file +/* ========================================================================== */ + + +async function getCustomMediaFromJSFile(from) { + const object = await import(from); + return getCustomMediaFromObject(object); +} +/* Get Custom Media from Sources +/* ========================================================================== */ + + +function getCustomMediaFromSources(sources) { + return sources.map(source => { + if (source instanceof Promise) { + return source; + } else if (source instanceof Function) { + return source(); + } // read the source as an object + + + const opts = source === Object(source) ? source : { + from: String(source) + }; // skip objects with custom media + + if (Object(opts).customMedia || Object(opts)['custom-media']) { + return opts; + } // source pathname + + + const from = path.resolve(String(opts.from || '')); // type of file being read from + + const type = (opts.type || path.extname(from).slice(1)).toLowerCase(); + return { + type, + from + }; + }).reduce(async (customMedia, source) => { + const { + type, + from + } = await source; + + if (type === 'css' || type === 'pcss') { + return Object.assign(await customMedia, await getCustomMediaFromCSSFile(from)); + } + + if (type === 'js') { + return Object.assign(await customMedia, await getCustomMediaFromJSFile(from)); + } + + if (type === 'json') { + return Object.assign(await customMedia, await getCustomMediaFromJSONFile(from)); + } + + return Object.assign(await customMedia, getCustomMediaFromObject(await source)); + }, {}); +} +/* Helper utilities +/* ========================================================================== */ + +const readFile = from => new Promise((resolve, reject) => { + fs.readFile(from, 'utf8', (error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }); +}); + +const readJSON = async from => JSON.parse(await readFile(from)); + +// return transformed medias, replacing custom pseudo medias with custom medias +function transformMediaList(mediaList, customMedias) { + let index = mediaList.nodes.length - 1; + + while (index >= 0) { + const transformedMedias = transformMedia(mediaList.nodes[index], customMedias); + + if (transformedMedias.length) { + mediaList.nodes.splice(index, 1, ...transformedMedias); + } + + --index; + } + + return mediaList; +} // return custom pseudo medias replaced with custom medias + +function transformMedia(media, customMedias) { + const transpiledMedias = []; + + for (const index in media.nodes) { + const { + value, + nodes + } = media.nodes[index]; + const key = value.replace(customPseudoRegExp, '$1'); + + if (key in customMedias) { + for (const replacementMedia of customMedias[key].nodes) { + // use the first available modifier unless they cancel each other out + const modifier = media.modifier !== replacementMedia.modifier ? media.modifier || replacementMedia.modifier : ''; + const mediaClone = media.clone({ + modifier, + // conditionally use the raws from the first available modifier + raws: !modifier || media.modifier ? { ...media.raws + } : { ...replacementMedia.raws + }, + type: media.type || replacementMedia.type + }); // conditionally include more replacement raws when the type is present + + if (mediaClone.type === replacementMedia.type) { + Object.assign(mediaClone.raws, { + and: replacementMedia.raws.and, + beforeAnd: replacementMedia.raws.beforeAnd, + beforeExpression: replacementMedia.raws.beforeExpression + }); + } + + mediaClone.nodes.splice(index, 1, ...replacementMedia.clone().nodes.map(node => { + // use raws and spacing from the current usage + if (media.nodes[index].raws.and) { + node.raws = { ...media.nodes[index].raws + }; + } + + node.spaces = { ...media.nodes[index].spaces + }; + return node; + })); // remove the currently transformed key to prevent recursion + + const nextCustomMedia = getCustomMediasWithoutKey(customMedias, key); + const retranspiledMedias = transformMedia(mediaClone, nextCustomMedia); + + if (retranspiledMedias.length) { + transpiledMedias.push(...retranspiledMedias); + } else { + transpiledMedias.push(mediaClone); + } + } + + return transpiledMedias; + } else if (nodes && nodes.length) { + transformMediaList(media.nodes[index], customMedias); + } + } + + return transpiledMedias; +} + +const customPseudoRegExp = /\((--[A-z][\w-]*)\)/; + +const getCustomMediasWithoutKey = (customMedias, key) => { + const nextCustomMedias = Object.assign({}, customMedias); + delete nextCustomMedias[key]; + return nextCustomMedias; +}; + +var transformAtrules = ((root, customMedia, opts) => { + root.walkAtRules(mediaAtRuleRegExp, atrule => { + if (customPseudoRegExp$1.test(atrule.params)) { + const mediaAST = mediaASTFromString(atrule.params); + const params = String(transformMediaList(mediaAST, customMedia)); + + if (opts.preserve) { + atrule.cloneBefore({ + params + }); + } else { + atrule.params = params; + } + } + }); +}); +const mediaAtRuleRegExp = /^media$/i; +const customPseudoRegExp$1 = /\(--[A-z][\w-]*\)/; + +/* Write Custom Media from CSS File +/* ========================================================================== */ + +async function writeCustomMediaToCssFile(to, customMedia) { + const cssContent = Object.keys(customMedia).reduce((cssLines, name) => { + cssLines.push(`@custom-media ${name} ${customMedia[name]};`); + return cssLines; + }, []).join('\n'); + const css = `${cssContent}\n`; + await writeFile(to, css); +} +/* Write Custom Media from JSON file +/* ========================================================================== */ + + +async function writeCustomMediaToJsonFile(to, customMedia) { + const jsonContent = JSON.stringify({ + 'custom-media': customMedia + }, null, ' '); + const json = `${jsonContent}\n`; + await writeFile(to, json); +} +/* Write Custom Media from Common JS file +/* ========================================================================== */ + + +async function writeCustomMediaToCjsFile(to, customMedia) { + const jsContents = Object.keys(customMedia).reduce((jsLines, name) => { + jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(customMedia[name])}'`); + return jsLines; + }, []).join(',\n'); + const js = `module.exports = {\n\tcustomMedia: {\n${jsContents}\n\t}\n};\n`; + await writeFile(to, js); +} +/* Write Custom Media from Module JS file +/* ========================================================================== */ + + +async function writeCustomMediaToMjsFile(to, customMedia) { + const mjsContents = Object.keys(customMedia).reduce((mjsLines, name) => { + mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(customMedia[name])}'`); + return mjsLines; + }, []).join(',\n'); + const mjs = `export const customMedia = {\n${mjsContents}\n};\n`; + await writeFile(to, mjs); +} +/* Write Custom Media to Exports +/* ========================================================================== */ + + +function writeCustomMediaToExports(customMedia, destinations) { + return Promise.all(destinations.map(async destination => { + if (destination instanceof Function) { + await destination(defaultCustomMediaToJSON(customMedia)); + } else { + // read the destination as an object + const opts = destination === Object(destination) ? destination : { + to: String(destination) + }; // transformer for custom media into a JSON-compatible object + + const toJSON = opts.toJSON || defaultCustomMediaToJSON; + + if ('customMedia' in opts) { + // write directly to an object as customMedia + opts.customMedia = toJSON(customMedia); + } else if ('custom-media' in opts) { + // write directly to an object as custom-media + opts['custom-media'] = toJSON(customMedia); + } else { + // destination pathname + const to = String(opts.to || ''); // type of file being written to + + const type = (opts.type || path.extname(to).slice(1)).toLowerCase(); // transformed custom media + + const customMediaJSON = toJSON(customMedia); + + if (type === 'css') { + await writeCustomMediaToCssFile(to, customMediaJSON); + } + + if (type === 'js') { + await writeCustomMediaToCjsFile(to, customMediaJSON); + } + + if (type === 'json') { + await writeCustomMediaToJsonFile(to, customMediaJSON); + } + + if (type === 'mjs') { + await writeCustomMediaToMjsFile(to, customMediaJSON); + } + } + } + })); +} +/* Helper utilities +/* ========================================================================== */ + +const defaultCustomMediaToJSON = customMedia => { + return Object.keys(customMedia).reduce((customMediaJSON, key) => { + customMediaJSON[key] = String(customMedia[key]); + return customMediaJSON; + }, {}); +}; + +const writeFile = (to, text) => new Promise((resolve, reject) => { + fs.writeFile(to, text, error => { + if (error) { + reject(error); + } else { + resolve(); + } + }); +}); + +const escapeForJS = string => string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r'); + +const creator = opts => { + // whether to preserve custom media and at-rules using them + const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : false; // sources to import custom media from + + const importFrom = [].concat(Object(opts).importFrom || []); // destinations to export custom media to + + const exportTo = [].concat(Object(opts).exportTo || []); // promise any custom media are imported + + const customMediaPromise = getCustomMediaFromSources(importFrom); + return { + postcssPlugin: 'postcss-custom-media', + Once: async root => { + const customMedia = Object.assign(await customMediaPromise, getCustomMediaFromRoot(root, { + preserve + })); + await writeCustomMediaToExports(customMedia, exportTo); + transformAtrules(root, customMedia, { + preserve + }); + } + }; +}; + +creator.postcss = true; + +export default creator; +//# sourceMappingURL=index.es.mjs.map diff --git a/src/node_modules/postcss-custom-media/package.json b/src/node_modules/postcss-custom-media/package.json new file mode 100644 index 0000000..17e580a --- /dev/null +++ b/src/node_modules/postcss-custom-media/package.json @@ -0,0 +1,108 @@ +{ + "_from": "postcss-custom-media", + "_id": "postcss-custom-media@8.0.0", + "_inBundle": false, + "_integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==", + "_location": "/postcss-custom-media", + "_phantomChildren": {}, + "_requested": { + "type": "tag", + "registry": true, + "raw": "postcss-custom-media", + "name": "postcss-custom-media", + "escapedName": "postcss-custom-media", + "rawSpec": "", + "saveSpec": null, + "fetchSpec": "latest" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz", + "_shasum": "1be6aff8be7dc9bf1fe014bde3b71b92bb4552f1", + "_spec": "postcss-custom-media", + "_where": "/src", + "author": { + "name": "Jonathan Neal", + "email": "jonathantneal@hotmail.com" + }, + "bugs": { + "url": "https://github.com/postcss/postcss-custom-media/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Maxime Thirouin" + } + ], + "deprecated": false, + "description": "Use Custom Media Queries in CSS", + "devDependencies": { + "@babel/core": "^7.11.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/preset-env": "^7.11.5", + "@rollup/plugin-babel": "^5.2.1", + "babel-eslint": "^10.1.0", + "eslint": "^7.10.0", + "postcss": "^8.1.0", + "postcss-tape": "^6.0.0", + "pre-commit": "^1.2.2", + "rollup": "^2.28.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "eslintConfig": { + "env": { + "browser": true, + "es6": true, + "node": true + }, + "extends": "eslint:recommended", + "parser": "babel-eslint", + "parserOptions": { + "ecmaVersion": 2018, + "impliedStrict": true, + "sourceType": "module" + } + }, + "files": [ + "index.cjs.js", + "index.es.mjs" + ], + "homepage": "https://github.com/postcss/postcss-custom-media#readme", + "keywords": [ + "postcss", + "css", + "postcss-plugin", + "custom", + "media", + "query", + "queries", + "w3c", + "csswg", + "atrule", + "at-rule", + "specification" + ], + "license": "MIT", + "main": "index.cjs.js", + "module": "index.es.mjs", + "name": "postcss-custom-media", + "peerDependencies": { + "postcss": "^8.1.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/postcss/postcss-custom-media.git" + }, + "scripts": { + "prepublishOnly": "npm test", + "pretest": "rollup -c .rollup.js --silent", + "test": "echo 'Running tests...'; npm run test:js && npm run test:tape", + "test:js": "eslint *.js lib/*.js --cache --ignore-path .gitignore --quiet", + "test:tape": "postcss-tape" + }, + "version": "8.0.0" +} diff --git a/src/package-lock.json b/src/package-lock.json new file mode 100644 index 0000000..1155683 --- /dev/null +++ b/src/package-lock.json @@ -0,0 +1,11 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "postcss-custom-media": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz", + "integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==" + } + } +}