From 23bd03f1bdc98871db5132c036c04f787025c9f2 Mon Sep 17 00:00:00 2001 From: JJimini Date: Sat, 13 Jul 2024 14:44:55 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20rfs=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _config.yml | 1 + assets/css/jekyll-theme-chirpy.scss | 1 + node_modules/.package-lock.json | 28 +- node_modules/fsevents/LICENSE | 22 + node_modules/fsevents/README.md | 89 ++++ node_modules/fsevents/fsevents.d.ts | 46 +++ node_modules/fsevents/fsevents.js | 83 ++++ node_modules/fsevents/fsevents.node | Bin 0 -> 163626 bytes node_modules/fsevents/package.json | 62 +++ node_modules/rfs/LICENSE | 21 + node_modules/rfs/README.md | 616 ++++++++++++++++++++++++++++ node_modules/rfs/less.less | 241 +++++++++++ node_modules/rfs/lib/rfs.js | 158 +++++++ node_modules/rfs/package.json | 104 +++++ node_modules/rfs/postcss.js | 153 +++++++ node_modules/rfs/sass.sass | 1 + node_modules/rfs/scss.scss | 348 ++++++++++++++++ node_modules/rfs/stylus.styl | 251 ++++++++++++ package-lock.json | 16 +- package.json | 3 +- 20 files changed, 2240 insertions(+), 4 deletions(-) create mode 100644 node_modules/fsevents/LICENSE create mode 100644 node_modules/fsevents/README.md create mode 100644 node_modules/fsevents/fsevents.d.ts create mode 100644 node_modules/fsevents/fsevents.js create mode 100755 node_modules/fsevents/fsevents.node create mode 100644 node_modules/fsevents/package.json create mode 100644 node_modules/rfs/LICENSE create mode 100644 node_modules/rfs/README.md create mode 100644 node_modules/rfs/less.less create mode 100644 node_modules/rfs/lib/rfs.js create mode 100644 node_modules/rfs/package.json create mode 100644 node_modules/rfs/postcss.js create mode 100644 node_modules/rfs/sass.sass create mode 100644 node_modules/rfs/scss.scss create mode 100644 node_modules/rfs/stylus.styl diff --git a/_config.yml b/_config.yml index 983a7abf..b6f68ce5 100644 --- a/_config.yml +++ b/_config.yml @@ -198,6 +198,7 @@ sass: style: compressed load_paths: - node_modules/bootstrap/scss + - node_modules/rfs/scss compress_html: diff --git a/assets/css/jekyll-theme-chirpy.scss b/assets/css/jekyll-theme-chirpy.scss index b6215ff3..54169db1 100644 --- a/assets/css/jekyll-theme-chirpy.scss +++ b/assets/css/jekyll-theme-chirpy.scss @@ -1,6 +1,7 @@ --- --- @import 'bootstrap'; +@import 'rfs'; @import 'main {%- if jekyll.environment == 'production' -%} diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 9ab86d05..134e9de7 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -5195,6 +5195,21 @@ "node": ">=14.14" } }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -9663,7 +9678,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, "license": "MIT" }, "node_modules/pretty-ms": { @@ -9987,6 +10001,18 @@ "node": ">=0.10.0" } }, + "node_modules/rfs": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/rfs/-/rfs-10.0.0.tgz", + "integrity": "sha512-Iu0N8fGAHDE6NZSc+S1aaY9ClaqkOdko+NvAstUS5sxRnzUgV20Ak0cOsMEP/vyYdzM3DOUOPKXH4XhfzMthvw==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/rollup": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", diff --git a/node_modules/fsevents/LICENSE b/node_modules/fsevents/LICENSE new file mode 100644 index 00000000..5d70441c --- /dev/null +++ b/node_modules/fsevents/LICENSE @@ -0,0 +1,22 @@ +MIT License +----------- + +Copyright (C) 2010-2020 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller + +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/node_modules/fsevents/README.md b/node_modules/fsevents/README.md new file mode 100644 index 00000000..50373a03 --- /dev/null +++ b/node_modules/fsevents/README.md @@ -0,0 +1,89 @@ +# fsevents + +Native access to MacOS FSEvents in [Node.js](https://nodejs.org/) + +The FSEvents API in MacOS allows applications to register for notifications of +changes to a given directory tree. It is a very fast and lightweight alternative +to kqueue. + +This is a low-level library. For a cross-platform file watching module that +uses fsevents, check out [Chokidar](https://github.com/paulmillr/chokidar). + +## Usage + +```sh +npm install fsevents +``` + +Supports only **Node.js v8.16 and higher**. + +```js +const fsevents = require('fsevents'); + +// To start observation +const stop = fsevents.watch(__dirname, (path, flags, id) => { + const info = fsevents.getInfo(path, flags); +}); + +// To end observation +stop(); +``` + +> **Important note:** The API behaviour is slightly different from typical JS APIs. The `stop` function **must** be +> retrieved and stored somewhere, even if you don't plan to stop the watcher. If you forget it, the garbage collector +> will eventually kick in, the watcher will be unregistered, and your callbacks won't be called anymore. + +The callback passed as the second parameter to `.watch` get's called whenever the operating system detects a +a change in the file system. It takes three arguments: + +###### `fsevents.watch(dirname: string, (path: string, flags: number, id: string) => void): () => Promise` + + * `path: string` - the item in the filesystem that have been changed + * `flags: number` - a numeric value describing what the change was + * `id: string` - an unique-id identifying this specific event + + Returns closer callback which when called returns a Promise resolving when the watcher process has been shut down. + +###### `fsevents.getInfo(path: string, flags: number, id: string): FsEventInfo` + +The `getInfo` function takes the `path`, `flags` and `id` arguments and converts those parameters into a structure +that is easier to digest to determine what the change was. + +The `FsEventsInfo` has the following shape: + +```js +/** + * @typedef {'created'|'modified'|'deleted'|'moved'|'root-changed'|'cloned'|'unknown'} FsEventsEvent + * @typedef {'file'|'directory'|'symlink'} FsEventsType + */ +{ + "event": "created", // {FsEventsEvent} + "path": "file.txt", + "type": "file", // {FsEventsType} + "changes": { + "inode": true, // Had iNode Meta-Information changed + "finder": false, // Had Finder Meta-Data changed + "access": false, // Had access permissions changed + "xattrs": false // Had xAttributes changed + }, + "flags": 0x100000000 +} +``` + +## Changelog + +- v2.3 supports Apple Silicon ARM CPUs +- v2 supports node 8.16+ and reduces package size massively +- v1.2.8 supports node 6+ +- v1.2.7 supports node 4+ + +## Troubleshooting + +- I'm getting `EBADPLATFORM` `Unsupported platform for fsevents` error. +- It's fine, nothing is broken. fsevents is macos-only. Other platforms are skipped. If you want to hide this warning, report a bug to NPM bugtracker asking them to hide ebadplatform warnings by default. + +## License + +The MIT License Copyright (C) 2010-2020 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller — see LICENSE file. + +Visit our [GitHub page](https://github.com/fsevents/fsevents) and [NPM Page](https://npmjs.org/package/fsevents) diff --git a/node_modules/fsevents/fsevents.d.ts b/node_modules/fsevents/fsevents.d.ts new file mode 100644 index 00000000..2723c048 --- /dev/null +++ b/node_modules/fsevents/fsevents.d.ts @@ -0,0 +1,46 @@ +declare type Event = "created" | "cloned" | "modified" | "deleted" | "moved" | "root-changed" | "unknown"; +declare type Type = "file" | "directory" | "symlink"; +declare type FileChanges = { + inode: boolean; + finder: boolean; + access: boolean; + xattrs: boolean; +}; +declare type Info = { + event: Event; + path: string; + type: Type; + changes: FileChanges; + flags: number; +}; +declare type WatchHandler = (path: string, flags: number, id: string) => void; +export declare function watch(path: string, handler: WatchHandler): () => Promise; +export declare function watch(path: string, since: number, handler: WatchHandler): () => Promise; +export declare function getInfo(path: string, flags: number): Info; +export declare const constants: { + None: 0x00000000; + MustScanSubDirs: 0x00000001; + UserDropped: 0x00000002; + KernelDropped: 0x00000004; + EventIdsWrapped: 0x00000008; + HistoryDone: 0x00000010; + RootChanged: 0x00000020; + Mount: 0x00000040; + Unmount: 0x00000080; + ItemCreated: 0x00000100; + ItemRemoved: 0x00000200; + ItemInodeMetaMod: 0x00000400; + ItemRenamed: 0x00000800; + ItemModified: 0x00001000; + ItemFinderInfoMod: 0x00002000; + ItemChangeOwner: 0x00004000; + ItemXattrMod: 0x00008000; + ItemIsFile: 0x00010000; + ItemIsDir: 0x00020000; + ItemIsSymlink: 0x00040000; + ItemIsHardlink: 0x00100000; + ItemIsLastHardlink: 0x00200000; + OwnEvent: 0x00080000; + ItemCloned: 0x00400000; +}; +export {}; diff --git a/node_modules/fsevents/fsevents.js b/node_modules/fsevents/fsevents.js new file mode 100644 index 00000000..198da98e --- /dev/null +++ b/node_modules/fsevents/fsevents.js @@ -0,0 +1,83 @@ +/* + ** © 2020 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller + ** Licensed under MIT License. + */ + +/* jshint node:true */ +"use strict"; + +if (process.platform !== "darwin") { + throw new Error(`Module 'fsevents' is not compatible with platform '${process.platform}'`); +} + +const Native = require("./fsevents.node"); +const events = Native.constants; + +function watch(path, since, handler) { + if (typeof path !== "string") { + throw new TypeError(`fsevents argument 1 must be a string and not a ${typeof path}`); + } + if ("function" === typeof since && "undefined" === typeof handler) { + handler = since; + since = Native.flags.SinceNow; + } + if (typeof since !== "number") { + throw new TypeError(`fsevents argument 2 must be a number and not a ${typeof since}`); + } + if (typeof handler !== "function") { + throw new TypeError(`fsevents argument 3 must be a function and not a ${typeof handler}`); + } + + let instance = Native.start(Native.global, path, since, handler); + if (!instance) throw new Error(`could not watch: ${path}`); + return () => { + const result = instance ? Promise.resolve(instance).then(Native.stop) : Promise.resolve(undefined); + instance = undefined; + return result; + }; +} + +function getInfo(path, flags) { + return { + path, + flags, + event: getEventType(flags), + type: getFileType(flags), + changes: getFileChanges(flags), + }; +} + +function getFileType(flags) { + if (events.ItemIsFile & flags) return "file"; + if (events.ItemIsDir & flags) return "directory"; + if (events.MustScanSubDirs & flags) return "directory"; + if (events.ItemIsSymlink & flags) return "symlink"; +} +function anyIsTrue(obj) { + for (let key in obj) { + if (obj[key]) return true; + } + return false; +} +function getEventType(flags) { + if (events.ItemRemoved & flags) return "deleted"; + if (events.ItemRenamed & flags) return "moved"; + if (events.ItemCreated & flags) return "created"; + if (events.ItemModified & flags) return "modified"; + if (events.RootChanged & flags) return "root-changed"; + if (events.ItemCloned & flags) return "cloned"; + if (anyIsTrue(flags)) return "modified"; + return "unknown"; +} +function getFileChanges(flags) { + return { + inode: !!(events.ItemInodeMetaMod & flags), + finder: !!(events.ItemFinderInfoMod & flags), + access: !!(events.ItemChangeOwner & flags), + xattrs: !!(events.ItemXattrMod & flags), + }; +} + +exports.watch = watch; +exports.getInfo = getInfo; +exports.constants = events; diff --git a/node_modules/fsevents/fsevents.node b/node_modules/fsevents/fsevents.node new file mode 100755 index 0000000000000000000000000000000000000000..1cc3345ead403e72439746aee6b40645893c322b GIT binary patch literal 163626 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 Is-vs_AMzay6aWAK literal 0 HcmV?d00001 diff --git a/node_modules/fsevents/package.json b/node_modules/fsevents/package.json new file mode 100644 index 00000000..5d0ee15e --- /dev/null +++ b/node_modules/fsevents/package.json @@ -0,0 +1,62 @@ +{ + "name": "fsevents", + "version": "2.3.3", + "description": "Native Access to MacOS FSEvents", + "main": "fsevents.js", + "types": "fsevents.d.ts", + "os": [ + "darwin" + ], + "files": [ + "fsevents.d.ts", + "fsevents.js", + "fsevents.node" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + }, + "scripts": { + "clean": "node-gyp clean && rm -f fsevents.node", + "build": "node-gyp clean && rm -f fsevents.node && node-gyp rebuild && node-gyp clean", + "test": "/bin/bash ./test.sh 2>/dev/null", + "prepublishOnly": "npm run build" + }, + "repository": { + "type": "git", + "url": "https://github.com/fsevents/fsevents.git" + }, + "keywords": [ + "fsevents", + "mac" + ], + "contributors": [ + { + "name": "Philipp Dunkel", + "email": "pip@pipobscure.com" + }, + { + "name": "Ben Noordhuis", + "email": "info@bnoordhuis.nl" + }, + { + "name": "Elan Shankar", + "email": "elan.shanker@gmail.com" + }, + { + "name": "Miroslav Bajtoš", + "email": "mbajtoss@gmail.com" + }, + { + "name": "Paul Miller", + "url": "https://paulmillr.com" + } + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/fsevents/fsevents/issues" + }, + "homepage": "https://github.com/fsevents/fsevents", + "devDependencies": { + "node-gyp": "^9.4.0" + } +} diff --git a/node_modules/rfs/LICENSE b/node_modules/rfs/LICENSE new file mode 100644 index 00000000..b42688c6 --- /dev/null +++ b/node_modules/rfs/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017-2019 Martijn Cuppens + +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/node_modules/rfs/README.md b/node_modules/rfs/README.md new file mode 100644 index 00000000..d953d509 --- /dev/null +++ b/node_modules/rfs/README.md @@ -0,0 +1,616 @@ +

+ RFS logo +

+ +RFS is a unit resizing engine which was initially developed to resize font sizes (hence its abbreviation for Responsive Font Sizes). Nowadays RFS is capable of rescaling basically every value for any css property with units, like `margin`, `padding`, `border-radius` or even `box-shadow`. + +The mechanism **automatically calculates the appropriate values** based on the dimensions of the browser viewport. It's available in one of your favourite preprocessors or postprocessor: [Sass](https://sass-lang.com/), [Less](http://lesscss.org/), [Stylus](http://stylus-lang.com/) or [PostCSS](https://postcss.org/). + +# RFS + +[![npm][npm-image]][npm-url] +[![licence][licence-image]][license-url] +[![build][build-image]][build-url] + +- [Demos](#demos) +- [Advantages](#advantages) +- [Installation](#installation) +- [Usage](#usage) +- [Visualisation](#visualisation) +- [Configuration](#configuration) +- [Creator](#creator) +- [Copyright and license](#copyright-and-license) + +## Demos + +- [Card example (Sass)](https://codepen.io/MartijnCuppens/pen/vqaEBG?editors=0100) +- [Card example (Sass, with custom properties)](https://codepen.io/MartijnCuppens/pen/voXLGL?editors=1100) +- [Card example (PostCSS)](https://codepen.io/MartijnCuppens/pen/aeojgG?editors=0100) +- [Card example (PostCSS, with custom properties)](https://codepen.io/MartijnCuppens/pen/JgRYaw?editors=0100) +- [Simple font rescaling Codepen Demo](https://codepen.io/MartijnCuppens/pen/ZBjdMy?editors=0100) +- [RFS in Bootstrap demo](https://project-rfs.github.io/) + +## Advantages + +- No need to rescale paddings or margins anymore. +- Text won't be chopped off in smaller viewports when RFS is applied to font sizes. +- RFS will prevent the font size from rescaling too small, so readability can be assured. +- The font sizes of all text elements will always remain in relation with each other. + +## Fluid rescaling in action + +The following example shows the effect of RFS on font sizes: + +![RFS](https://raw.githubusercontent.com/twbs/rfs/main/.github/rfs-rescale.gif) + +## Installation + +RFS can be installed using a package manager (recommended): + +- npm: `npm install rfs` +- yarn: `yarn add rfs` +- bower (deprecated): `bower install rfs --save` + +**Copy/paste (not recommended):** + +The source files can also be downloaded manually and used in a project. This method is not recommended because you +lose the ability to easily and quickly manage and update RFS as a dependency. + +## Usage + +### Sass (.scss syntax) + +```text +project/ +├── node_modules/ +│ └── rfs +│ └── ... +└── scss/ + └── main.scss +``` + +#### Input + +```scss +// scss/main.scss + +@import "../node_modules/rfs/scss"; + +.title { + @include font-size(4rem); + + // The font-size mixin is a shorthand which calls + // @include rfs(4rem, font-size); + + // Other shorthand mixins that are available are: + // @include padding(4rem); + // @include padding-top(4rem); + // @include padding-right(4rem); + // @include padding-bottom(4rem); + // @include padding-left(4rem); + // @include margin(4rem); + // @include margin-top(4rem); + // @include margin-right(4rem); + // @include margin-bottom(4rem); + // @include margin-left(4rem); + + // For properties which do not have a shorthand, the property can be passed: + // @include rfs(4rem, border-radius); + + // Whenever a value contains a comma, it should be escaped with `#{}`: + // @include rfs(0 0 4rem red #{","} 0 0 5rem blue, box-shadow); + + // Custom properties (css variables): + // @include rfs(4rem, --border-radius); +} +``` + +If you're using Webpack, you can simplify the `@import` using the `~` prefix: + +```scss +@import "~rfs/scss"; +``` + +#### Generated css + +```css +.title { + font-size: calc(1.525rem + 3.3vw); +} + +@media (min-width: 1200px) { + .title { + font-size: 4rem; + } +} +``` + +#### !important usage + +##### Input + +```scss +.label { + @include font-size(2.5rem !important); +} +``` + +##### Output + +```css +.label { + font-size: calc(1.375rem + 1.5vw) !important; +} + +@media (min-width: 1200px) { + .label { + font-size: 2.5rem !important; + } +} +``` + +### Sass (`.sass` syntax) + +```text +project/ +├── node_modules/ +│ └── rfs +│ └── ... +└── sass/ + └── main.sass +``` + +#### Input + +```sass +// sass/main.sass + +@import "../node_modules/rfs/sass" + +.title + +font-size(4rem) + + // The font-size mixin is a shorthand which calls + // +rfs(4rem, font-size) + + // Other shorthand mixins that are available are: + // +padding(4rem) + // +padding-top(4rem) + // +padding-right(4rem) + // +padding-bottom(4rem) + // +padding-left(4rem) + // +margin(4rem) + // +margin-top(4rem) + // +margin-right(4rem) + // +margin-bottom(4rem) + // +margin-left(4rem) + + // For properties which do not have a shorthand, the property can be passed: + // +rfs(4rem, border-radius) + + // Whenever a value contains a comma, it should be escaped with `#{}`: + // +rfs(0 0 4rem red #{","} 0 0 5rem blue, box-shadow) + + // Custom properties (css variables): + // +rfs(4rem, --border-radius) +``` + +If you're using Webpack, you can simplify the `@import` using the `~` prefix: + +```sass +@import "~rfs/scss" +``` + +#### Generated css + +```css +.title { + font-size: calc(1.525rem + 3.3vw); +} + +@media (min-width: 1200px) { + .title { + font-size: 4rem; + } +} +``` + +#### !important usage + +##### Input + +```sass +.label + +font-size(2.5rem !important) +``` + +#### output + +```css +.label { + font-size: calc(1.375rem + 1.5vw) !important; +} + +@media (min-width: 1200px) { + .label { + font-size: 2.5rem !important; + } +} +``` + +### PostCSS + +```text +project/ +├── postcss/ +│ └── main.css +└── node_modules/ + └── rfs + └── ... +``` + +Have a look at the [examples folder](https://github.com/twbs/rfs/tree/main/examples/postcss) to find examples on how your PostCSS setup can be configured. + +```postcss +// postcss/main.css + +.title { + font-size: rfs(4rem); + + // Or use it with any other property, for example + // padding: rfs(4rem); + + // It's also possible to pass multiple values + // padding: rfs(3rem 4rem); + + // or even + // box-shadow: rfs(0 3px 4rem red); + + // or even comma seperated values + // box-shadow: rfs(0 3px 4rem red, 3px 0 4rem blue); + + // To combine it with !important, use + // box-shadow: rfs(0 3px 4rem red) !important; + + // Custom properties (css variables): + // --border-radius: rfs(4rem); +} +``` + +#### Generated css + +```css +.title { + font-size: calc(1.525rem + 3.3vw); +} + +@media (min-width: 1200px) { + .title { + font-size: 4rem; + } +} +``` + +### Less + +```text +project/ +├── less/ +│ └── main.less +└── node_modules/ + └── rfs + └── ... +``` + +```less +// less/main.less + +@import "../node_modules/rfs/less"; + +.title { + .font-size(4rem); + + // The font-size mixin is a shorthand which calls + // .rfs(4rem, font-size); + + // Other shorthand mixins that are available are: + // .padding(4rem); + // .padding-top(4rem); + // .padding-right(4rem); + // 'padding-bottom(4rem); + // .padding-left(4rem); + // .margin(4rem); + // .margin-top(4rem); + // .margin-right(4rem); + // .margin-bottom(4rem); + // .margin-left(4rem); + + // For properties which do not have a shorthand, the property can be passed as: + // .rfs(4rem, border-radius); + + // Whenever a value contains a comma, it should be escaped with a tilde(~): + // .rfs(0 0 4rem red ~"," 0 0 5rem blue, box-shadow) + + // Custom properties (css variables): + // .rfs(4rem, --border-radius) +} +``` + +If you're using Webpack, you can simplify the `@import` using the `~` prefix: + +```less +@import "~rfs/less" +``` + +#### Generated css + +```css +.title { + font-size: calc(1.525rem + 3.3vw); +} + +@media (min-width: 1200px) { + .title { + font-size: 4rem; + } +} +``` + +#### !important usage + +Less still has [a bug](https://github.com/less/less.js/issues/2917) for [native `!important` support](http://lesscss.org/features/#mixins-feature-the-important-keyword), and `!important` can not be accepted as a parameter, so you 'll need to pass `important` as a flag: + +##### Input + +```less +.label { + .font-size(2.5rem important); +} +``` + +#### output + +```css +.label { + font-size: calc(1.375rem + 1.5vw) !important; +} + +@media (min-width: 1200px) { + .label { + font-size: 2.5rem !important; + } +} +``` + +### Stylus + +```text +project/ +├── node_modules/ +│ └── rfs +│ └── ... +└── stylus/ + └── main.styl +``` + +```stylus +// stylus/main.styl + +@import "../node_modules/rfs/stylus"; + +.title + rfs-font-size(64px) + + // The font-size mixin is a shorthand which calls + // rfs(4rem, font-size) + + // Other shorthand mixins that are available are: + // rfs-padding(4rem) + // rfs-padding-top(4rem) + // rfs-padding-right(4rem) + // rfs-padding-bottom(4rem) + // rfs-padding-left(4rem) + // rfs-margin(4rem) + // rfs-margin-top(4rem) + // rfs-margin-right(4rem) + // rfs-margin-bottom(4rem) + // rfs-margin-left(4rem) + + // For properties which do not have a shorthand, the property can be passed as: + // rfs(4rem, border-radius) + + // Whenever a value contains a comma, it should be escaped with a backslash: + // rfs(0 0 4rem red \, 0 0 5rem blue, box-shadow) + + // Custom properties (css variables): + // rfs(4rem, --border-radius) +``` + +Note the `font-size` mixin can not be used to set the font size. That is because a `font-size()` mixin would override the `font-size` property. See [129#issuecomment-477926416](https://github.com/twbs/rfs/pull/129#issuecomment-477926416) for more info. + +If you're using Webpack, you can simplify the `@import` using the `~` prefix: + +```stylus +@import "~rfs/stylus" +``` + +#### Generated css + +```css +.title { + font-size: calc(1.525rem + 3.3vw); +} + +@media (min-width: 1200px) { + .title { + font-size: 4rem; + } +} +``` + +#### !important usage + +##### Input + +```less +.label + rfs-font-size(2.5rem important) +``` + +#### output + +```css +.label { + font-size: calc(1.375rem + 1.5vw) !important; +} + +@media (min-width: 1200px) { + .label { + font-size: 2.5rem !important; + } +} +``` + +## Visualisation + +If you wonder how the values are rescaled, wonder no more and stare at this graph which might clarify things a bit: + +![RFS visualisation](https://raw.githubusercontent.com/twbs/rfs/main/.github/rfs-graph.svg?sanitize=true) + +Each color represents another value being rescaled. For example: + +```scss +.title { + @include font-size(40px); +} +``` + +This is the green line. A font size of `40px` stays `40px` in viewports with a size larger than `1200px`. Below `1200px`, the font size is rescaled and at viewport of `360px`, the font size is about `27px`. Note that every font size is generated in a combination of `rem` and `vw` units, but they are mapped to `px` in the graph to make it easier to understand. + +## Configuration + +RFS works out of the box without any configuration tweaks, but if you feel the urge to go loco and fine tune the way values are rescaled, you can: + +### Base value (unit in `px` or `rem`) + +- SCSS, Sass & Stylus: `$rfs-base-value` +- Less: `@rfs-base-value` +- PostCSS: `baseValue` + +The option will prevent the value from becoming too small on smaller screens. If the font size which is passed to RFS is smaller than this value, no fluid rescaling will take place. + +*Default value: `1.25rem`* + +### Unit (`px` or `rem`) + +- SCSS, Sass & Stylus: `$rfs-unit` +- Less: `@rfs-unit` +- PostCSS: `unit` + +The output value will be rendered in this unit. Keep in mind configuring this value to `px` will disable the ability for users to change the the font size in their browser. + +*Default value: `rem`* + +### Breakpoint (in `px`, `em` or `rem`) + +- SCSS, Sass & Stylus: `$rfs-breakpoint` +- Less: `@rfs-breakpoint` +- PostCSS: `breakpoint` + +Above this breakpoint, the value will be equal to the value you passed to RFS; below the breakpoint, the value will dynamically scale. + +*Default value: `1200px`* + +### Breakpoint unit (`px`, `em` or `rem`) + +- SCSS, Sass & Stylus: `$rfs-breakpoint-unit` +- Less: `@rfs-breakpoint-unit` +- PostCSS: `breakpointUnit` + +The width of the max width in the media query will be rendered in this unit. + +*Default value: `px`* + +### Factor (number) + +- SCSS, Sass & Stylus: `$rfs-factor` +- Less: `@rfs-factor` +- PostCSS: `factor` + +This value determines the strength of font size resizing. The higher the factor, the less difference there is between values on small screens. The lower the factor, the less influence RFS has, which results in bigger values for small screens. The factor must be greater than 1. + +*Default value: `10`* + +### Rem value (number) + +- SCSS, Sass & Stylus: `$rfs-rem-value` +- Less: `@rfs-rem-value` +- PostCSS: `remValue` + +The value of `1rem` in `px`. The value of `1rem` is typically `16px` but if the font size is changed for `html` the value of `1rem` changes. This variable can be used to change the default value but be careful with it because changing it could lead to unexpected behaviour, for example if additional CSS is loaded which expects `1rem` to be `16px`. + +*Default value: `16`* + +### Two dimensional (boolean) + +- SCSS, Sass & Stylus: `$rfs-two-dimensional` +- Less: `@rfs-two-dimensional` +- PostCSS: `twoDimensional` + +Enabling the two dimensional media queries will determine the value based on the smallest side of the screen with `vmin`. This prevents values from changing if the device toggles between portrait and landscape mode. + +*Default value: `false`* + +### Class (boolean) + +- SCSS, Sass & Stylus: `$rfs-class` +- Less: `@rfs-class` +- PostCSS: `class` + +RFS can be enabled or disabled with a class. There are 3 options: + +- `false` + No extra classes are generated. +- `disable` + When the the disable classes are generated you can add the `.disable-rfs` class to an element to disable responsive value rescaling for the element and its child elements. +- `enable` + RFS is disabled by default in this case. The `.enable-rfs` class can be added to an element to enable responsive value rescaling for the element and its child elements. + +*Default value: `false`* + +### Safari iframe resize bug fix (boolean) + +- SCSS, Sass & Stylus: `$rfs-safari-iframe-resize-bug-fix` +- Less: `@rfs-safari-iframe-resize-bug-fix` +- PostCSS: `safariIframeResizeBugFix` + +Safari doesn't resize its values in an iframe if the iframe is resized. To fix this `min-width: 0vw` can be added and that's what happens if this option is enabled. See [#14](https://github.com/twbs/rfs/issues/14). + +*Default value: `false`* + +## Best practices + +- Don't set RFS on the `html` element, because this influences the value of `rem` and could lead to unexpected results. +- Always set your line-heights relative (in `em` or unitless) to prevent interline issues with font sizes. + +## Browser support + +RFS is supported by all browsers that support [media queries](https://caniuse.com/#feat=css-mediaqueries) and [viewport units](https://caniuse.com/#feat=viewport-units). + +## Creator + +**Martijn Cuppens** + +- +- + +## Copyright and license + +Code released under [the MIT license](https://github.com/twbs/rfs/blob/main/LICENSE). + +[npm-image]: https://img.shields.io/npm/v/rfs?logo=npm&logoColor=fff +[npm-url]: https://www.npmjs.com/package/rfs +[licence-image]: https://img.shields.io/npm/l/rfs +[license-url]: https://github.com/twbs/rfs/blob/main/LICENSE +[build-image]: https://img.shields.io/github/actions/workflow/status/twbs/rfs/test.yml?branch=main&label=Tests&logo=github +[build-url]: https://github.com/twbs/rfs/actions?query=workflow%3ATests+branch%3Amain diff --git a/node_modules/rfs/less.less b/node_modules/rfs/less.less new file mode 100644 index 00000000..8e4834ee --- /dev/null +++ b/node_modules/rfs/less.less @@ -0,0 +1,241 @@ +// stylelint-disable selector-max-combinators, selector-max-compound-selectors + +// Less RFS mixin +// +// Automated responsive values for font sizes, paddings, margins and much more +// +// See https://github.com/twbs/rfs + +// Configuration + +// Base value +@rfs-base-value: 1.25rem; +@rfs-unit: rem; + +// Breakpoint at where value stops increasing +@rfs-breakpoint: 1200px; +@rfs-breakpoint-unit: px; + +// Resize value based on screen height and width +@rfs-two-dimensional: false; + +// Factor of decrease +@rfs-factor: 10; + +// Mode. Possibilities: "min-media-query", "max-media-query" +@rfs-mode: "min-media-query"; + +// Generate enable or disable classes. Possibilities: false, "enable" or "disable" +@rfs-class: false; + +// 1 rem = @rfs-rem-value px +@rfs-rem-value: 16; + +// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14 +@rfs-safari-iframe-resize-bug-fix: false; + +// Disable RFS by setting @enable-rfs to false +@enable-rfs: true; + +// RFS mixin +.rfs(@values, @property: font-size) { + ._rfs-calculate(1, ~"", ~""); +} + +// Recursive calculate mixin +._rfs-calculate(@index, @valueResult, @fluidValueResult) { + + & when (@index <= length(@values)) { + @currentValue: if(extract(@values, @index) = important, ~"!important" , extract(@values, @index)); + @space: if(@index = length(@values), ~"", ~" "); + + & when (not(isunit(@currentValue, px)) and not(isunit(@currentValue, rem))) { + ._rfs-calculate((@index + 1), ~"@{valueResult}@{currentValue}@{space}", ~"@{fluidValueResult}@{currentValue}@{space}"); + } + + & when ((isunit(@currentValue, px)) or (isunit(@currentValue, rem))) { + @val: if(isunit(@currentValue, rem), unit((@currentValue * @rfs-rem-value)), unit(@currentValue)); + + // Remove unit if zero + @value-unit: if(@val = 0, ~"", @rfs-unit); + + @renderedValue: unit(if(@rfs-unit = px, @val, ((@val / @rfs-rem-value))), @value-unit); + + @rfs-min: if(isunit(@rfs-base-value, rem), unit((@rfs-base-value * @rfs-rem-value)), unit(@rfs-base-value)); + + & when (not((abs(@val) > @rfs-min) and (@rfs-factor > 1) and (@enable-rfs = true))) { + ._rfs-calculate((@index + 1), ~"@{valueResult}@{renderedValue}@{space}", ~"@{fluidValueResult}@{renderedValue}@{space}"); + } + + & when ((abs(@val) > @rfs-min) and (@rfs-factor > 1) and (@enable-rfs = true)) { + + @breakpoint: if(isunit(@rfs-breakpoint, em) or isunit(@rfs-breakpoint, rem), unit((@rfs-breakpoint * @rfs-rem-value)), unit(@rfs-breakpoint)); + @max-width: unit(if(@rfs-breakpoint-unit = px, @breakpoint, ((@breakpoint / @rfs-rem-value))), @rfs-breakpoint-unit); + + // Calculate minimum value + @value-min: @rfs-min + (((abs(@val) - @rfs-min) / @rfs-factor)); + + // Calculate difference between @val and the minimum value + // Rounding needed to prevent rounding errors + @value-variable-width: unit(round(((abs(@val) - @value-min) / ((@breakpoint / 100))), 15), if(@rfs-two-dimensional, vmin, vw)); + + & when (@val > 0) { + @renderedFluidValue: calc(unit(if(@rfs-unit = px, ((@value-min)), ((@value-min / @rfs-rem-value))), @rfs-unit) ~"+" @value-variable-width); + ._rfs-calculate((@index + 1), ~"@{valueResult}@{renderedValue}@{space}", ~"@{fluidValueResult}@{renderedFluidValue}@{space}"); + } + + & when (@val < 0) { + @renderedFluidValue: calc(unit(if(@rfs-unit = px, ((-@value-min)), ((-@value-min / @rfs-rem-value))), @rfs-unit) ~"-" @value-variable-width); + ._rfs-calculate((@index + 1), ~"@{valueResult}@{renderedValue}@{space}", ~"@{fluidValueResult}@{renderedFluidValue}@{space}"); + } + } + } + } + + & when (@index > length(@values)) { + @fluidValue: @fluidValueResult; + + & when (@valueResult = @fluidValueResult) { + @{property}: @valueResult; + } + + & when (not(@valueResult = @fluidValueResult)) { + + & when (@rfs-class = "disable") and (@rfs-mode = "max-media-query") { + &, + .disable-rfs &, + &.disable-rfs { + @{property}: @valueResult; + } + } + + & when (@rfs-class = "enable") and (@rfs-mode = "min-media-query") { + @{property}: @valueResult; + + .enable-rfs &, + &.enable-rfs { + @{property}: @fluidValue; + } + } + + & when (not((@rfs-class = "disable") and (@rfs-mode = "max-media-query"))) and not((@rfs-class = "enable") and (@rfs-mode = "min-media-query")) { + @{property}: if(@rfs-mode = "min-media-query", @fluidValue, @valueResult); + } + + // Media query + & when (@rfs-class = "enable") { + .enable-rfs &, + &.enable-rfs { + ._rfs-render-media-query(); + } + } + + & when (@rfs-class = "disable") and (@rfs-mode = "min-media-query") { + .disable-rfs &, + &.disable-rfs { + @{property}: @valueResult; + } + + ._rfs-render-media-query(); + } + + & when (not(@rfs-class = "enable")) and not(@rfs-class = "disable") { + ._rfs-render-media-query(); + } + + & when ((@rfs-safari-iframe-resize-bug-fix)) { + // stylelint-disable-next-line length-zero-no-unit + min-width: 0vw; + } + } + } +} + +._rfs-render-media-query () { + & when (@rfs-two-dimensional) { + & when (@rfs-mode = "min-media-query") { + @media (min-width: @max-width) and (min-height: @max-width) { + @{property}: @valueResult; + } + } + + & when (@rfs-mode = "max-media-query") { + @media (max-width: @max-width), (max-height: @max-width) { + @{property}: @fluidValue; + } + } + } + + & when (not(@rfs-two-dimensional)) { + & when (@rfs-mode = "min-media-query") { + @media (min-width: @max-width) { + @{property}: @valueResult; + } + } + + & when (@rfs-mode = "max-media-query") { + @media (max-width: @max-width) { + @{property}: @fluidValue; + } + } + } +} + +._rfs-render-media-query-content() { + + & when (@rfs-class = "enable") { + .enable-rfs &, + &.enable-rfs { + @{property}: if(@rfs-mode = "min-media-query", @valueResult, @fluidValue); + } + } + + & when (not(@rfs-class = "enable")) { + @{property}: if(@rfs-mode = "min-media-query", @valueResult, @fluidValue); + } +} + +// Sharthand mixins +.font-size(@value) { + .rfs(@value); +} + +.padding(@value, @property: padding) { + .rfs(@value, @property); +} + +.padding-top(@value, @property: padding-top) { + .rfs(@value, @property); +} + +.padding-right(@value, @property: padding-right) { + .rfs(@value, @property); +} + +.padding-bottom(@value, @property: padding-bottom) { + .rfs(@value, @property); +} + +.padding-left(@value, @property: padding-left) { + .rfs(@value, @property); +} + +.margin(@value, @property: margin) { + .rfs(@value, @property); +} + +.margin-top(@value, @property: margin-top) { + .rfs(@value, @property); +} + +.margin-right(@value, @property: margin-right) { + .rfs(@value, @property); +} + +.margin-bottom(@value, @property: margin-bottom) { + .rfs(@value, @property); +} + +.margin-left(@value, @property: margin-left) { + .rfs(@value, @property); +} diff --git a/node_modules/rfs/lib/rfs.js b/node_modules/rfs/lib/rfs.js new file mode 100644 index 00000000..0fbc332c --- /dev/null +++ b/node_modules/rfs/lib/rfs.js @@ -0,0 +1,158 @@ +'use strict'; + +const postcss = require('postcss'); +const valueParser = require('postcss-value-parser'); + +const defaultOptions = { + baseValue: 20, + unit: 'rem', + breakpoint: 1200, + breakpointUnit: 'px', + factor: 10, + twoDimensional: false, + unitPrecision: 5, + remValue: 16, + functionName: 'rfs', + enableRfs: true, + mode: 'min-media-query' +}; + +module.exports = class { + constructor(opts) { + this.opts = { ...defaultOptions, ...opts }; + + if (typeof this.opts.baseValue !== 'number') { + if (this.opts.baseValue.endsWith('px')) { + this.opts.baseValue = Number.parseFloat(this.opts.baseValue); + } else if (this.opts.baseValue.endsWith('rem')) { + this.opts.baseValue = Number.parseFloat(this.opts.baseValue) * this.opts.remValue; + } else { + throw new TypeError('`baseValue` option is invalid, it should be set in `px` or `rem`.'); + } + } + + if (typeof this.opts.breakpoint !== 'number') { + if (this.opts.breakpoint.endsWith('px')) { + this.opts.breakpoint = Number.parseFloat(this.opts.breakpoint); + } else if (this.opts.breakpoint.endsWith('em')) { + this.opts.breakpoint = Number.parseFloat(this.opts.breakpoint) * this.opts.remValue; + } else { + throw new TypeError('`breakpoint` option is invalid, it should be set in `px`, `rem` or `em`.'); + } + } + + if (!['px', 'rem', 'em'].includes(this.opts.breakpointUnit)) { + throw new TypeError('`breakpointUnit` option is invalid, it should be `px`, `rem` or `em`.'); + } + } + + toFixed(number, precision) { + const multiplier = 10 ** (precision + 1); + const wholeNumber = Math.floor(number * multiplier); + + return Math.round(wholeNumber / 10) * 10 / multiplier; + } + + renderValue(value) { + // Do not add unit if value is 0 + if (value === 0) { + return value; + } + + // Render value in desired unit + return this.opts.unit === 'rem' ? + `${this.toFixed(value / this.opts.remValue, this.opts.unitPrecision)}rem` : + `${this.toFixed(value, this.opts.unitPrecision)}px`; + } + + process(declarationValue, fluid) { + const parsed = valueParser(declarationValue); + + // Function walk() will visit all the of the nodes in the tree, + // invoking the callback for each. + parsed.walk(node => { + // Since we only want to transform rfs() values, + // we can ignore everything else. + if (node.type !== 'function' && node.value !== this.opts.functionName) { + return; + } + + const wordNodes = node.nodes.filter(node => node.type === 'word'); + + for (const node of wordNodes) { + node.value = node.value.replace(/^(-?\d*\.?\d+)(.*)/g, (match, value, unit) => { + value = Number.parseFloat(value); + + // Return value if it's not a number or px/rem value + if (Number.isNaN(value) || !['px', 'rem'].includes(unit)) { + return match; + } + + // Convert to px if in rem + if (unit === 'rem') { + value *= this.opts.remValue; + } + + // Only add responsive function if needed + if (!fluid || this.opts.baseValue >= Math.abs(value) || this.opts.factor <= 1 || !this.opts.enableRfs) { + return this.renderValue(value); + } + + // Calculate base and difference + let baseValue = this.opts.baseValue + ((Math.abs(value) - this.opts.baseValue) / this.opts.factor); + const diff = Math.abs(value) - baseValue; + + // Divide by remValue if needed + if (this.opts.unit === 'rem') { + baseValue /= this.opts.remValue; + } + + const viewportUnit = this.opts.twoDimensional ? 'vmin' : 'vw'; + + return value > 0 ? + `calc(${this.toFixed(baseValue, this.opts.unitPrecision)}${this.opts.unit} + ${this.toFixed(diff * 100 / this.opts.breakpoint, this.opts.unitPrecision)}${viewportUnit})` : + `calc(-${this.toFixed(baseValue, this.opts.unitPrecision)}${this.opts.unit} - ${this.toFixed(diff * 100 / this.opts.breakpoint, this.opts.unitPrecision)}${viewportUnit})`; + }); + } + + // Now we will transform the existing rgba() function node + // into a word node with the hex value + node.type = 'word'; + node.value = valueParser.stringify(node.nodes); + }); + + return parsed.toString(); + } + + // Return the value without `rfs()` function + // eg. `4px rfs(32px)` => `.25rem 2rem` + value(value) { + return this.process(value, false); + } + + // Convert `rfs()` function to fluid css + // eg. `4px rfs(32px)` => `.25rem calc(1.325rem + 0.9vw)` + fluidValue(value) { + return this.process(value, true); + } + + renderMediaQuery() { + const mediaQuery = { + name: 'media' + }; + + const dimPrefix = this.opts.mode === 'min-media-query' ? 'min' : 'max'; + const dimConnector = this.opts.mode === 'min-media-query' ? ' and' : ','; + const breakpoint = this.opts.breakpointUnit === 'px' ? this.opts.breakpoint : this.opts.breakpoint / this.opts.remValue; + + mediaQuery.params = this.opts.twoDimensional ? + `(${dimPrefix}-width: ${breakpoint}${this.opts.breakpointUnit})${dimConnector} (${dimPrefix}-height: ${breakpoint}${this.opts.breakpointUnit})` : + `(${dimPrefix}-width: ${breakpoint}${this.opts.breakpointUnit})`; + + return postcss.atRule(mediaQuery); + } + + getOptions() { + return this.opts; + } +}; diff --git a/node_modules/rfs/package.json b/node_modules/rfs/package.json new file mode 100644 index 00000000..cae2f90a --- /dev/null +++ b/node_modules/rfs/package.json @@ -0,0 +1,104 @@ +{ + "name": "rfs", + "version": "10.0.0", + "main": "postcss.js", + "description": "Powerful & easy-to-use responsive resizing engine.", + "author": "Martijn Cuppens ", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/twbs/rfs.git" + }, + "bugs": { + "url": "https://github.com/twbs/rfs/issues" + }, + "homepage": "https://github.com/twbs/rfs#readme", + "files": [ + "lib/", + "less.less", + "postcss.js", + "sass.sass", + "scss.scss", + "stylus.styl" + ], + "keywords": [ + "rfs", + "fluid", + "responsive", + "font-size", + "typography", + "mixin", + "scss", + "sass", + "less", + "stylus", + "postcss" + ], + "engines": { + "node": ">=12" + }, + "scripts": { + "mocha": "mocha", + "stylelint": "stylelint \"**/*.{less,scss}\" --cache --cache-location node_modules/.cache/stylelint --rd", + "xo": "xo", + "lint": "npm-run-all --parallel --aggregate-output --continue-on-error xo stylelint", + "test": "npm run lint && npm run mocha", + "generate-test-results": "node-sass test/sass/ -o test/expected/ && prettier --write test/expected/*.css", + "examples": "npm-run-all --parallel --aggregate-output --continue-on-error gulp-examples node-examples", + "gulp-examples": "npm-run-all --parallel --aggregate-output --continue-on-error gulp-example-*", + "gulp-example-less": "gulp --gulpfile=examples/less/gulpfile.js", + "gulp-example-postcss": "gulp --gulpfile=examples/postcss/gulpfile.js", + "gulp-example-scss": "gulp --gulpfile=examples/scss/gulpfile.js", + "gulp-example-stylus": "gulp --gulpfile=examples/stylus/gulpfile.js", + "node-examples": "npm-run-all --parallel --aggregate-output --continue-on-error node-example-*", + "node-example-less": "node examples/less/index.js", + "node-example-postcss": "node examples/postcss/index.js", + "node-example-scss": "node examples/scss/index.js", + "node-example-stylus": "node examples/stylus/index.js" + }, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "devDependencies": { + "gulp": "^4.0.2", + "gulp-less": "^5.0.0", + "gulp-postcss": "^9.0.1", + "gulp-sass": "^5.1.0", + "gulp-stylus": "^3.0.0", + "less": "^4.1.3", + "less3": "npm:less@^3.13.1", + "mocha": "^9.2.2", + "node-sass": "^8.0.0", + "npm-run-all": "^4.1.5", + "postcss": "^8.4.21", + "postcss-less": "^6.0.0", + "prettier": "^2.8.5", + "sass": "^1.59.3", + "stylelint": "^14.16.1", + "stylelint-config-twbs-bootstrap": "^7.0.0", + "stylus": "^0.59.0", + "xo": "^0.52.4" + }, + "xo": { + "space": true, + "rules": { + "arrow-body-style": "off", + "comma-dangle": [ + "error", + "never" + ], + "n/prefer-promises/fs": "off", + "object-curly-spacing": [ + "error", + "always" + ], + "operator-linebreak": [ + "error", + "after" + ], + "prefer-template": "error", + "unicorn/prefer-module": "off", + "unicorn/prevent-abbreviations": "off" + } + } +} diff --git a/node_modules/rfs/postcss.js b/node_modules/rfs/postcss.js new file mode 100644 index 00000000..7c6258f4 --- /dev/null +++ b/node_modules/rfs/postcss.js @@ -0,0 +1,153 @@ +/*! + * PostCSS RFS plugin + * + * Automated responsive values for font sizes, paddings, margins and much more + * + * Licensed under MIT (https://github.com/twbs/rfs/blob/main/LICENSE) + */ + +'use strict'; + +const postcss = require('postcss'); +const RfsClass = require('./lib/rfs.js'); + +const DISABLE_RFS_SELECTOR = '.disable-rfs'; +const ENABLE_RFS_SELECTOR = '.enable-rfs'; + +module.exports = (opts = {}) => { + const rfs = new RfsClass(opts); + + // Get the merged options + opts = rfs.getOptions(); + const mediaQuery = rfs.renderMediaQuery(); + + return css => { + css.walkRules(rule => { + const mediaQueryRules = []; + const extraBlocks = []; + const { parent } = rule; + let removeRule = false; + let dcRule; + let ecRule; + let ruleSelector = rule.selector; + + // Prepare rule to add to media query + if (opts.class === 'enable') { + const selectors = rule.selector.split(','); + let tempRuleSelector = ''; + + for (const selector of selectors) { + tempRuleSelector += `${ENABLE_RFS_SELECTOR} ${selector},\n`; + tempRuleSelector += `${selector + ENABLE_RFS_SELECTOR},\n`; + } + + ruleSelector = tempRuleSelector.slice(0, -2); + } + + const fluidRule = postcss.rule({ + selector: ruleSelector + }); + + // Disable classes + if (opts.class === 'disable') { + const selectors = rule.selector.split(','); + let ruleSelector = ''; + + for (const selector of selectors) { + ruleSelector += opts.mode === 'max-media-query' ? `${selector},\n` : ''; + ruleSelector += `${DISABLE_RFS_SELECTOR} ${selector},\n`; + ruleSelector += `${selector + DISABLE_RFS_SELECTOR},\n`; + } + + ruleSelector = ruleSelector.slice(0, -2); + + dcRule = postcss.rule({ + selector: ruleSelector, + source: rule.source + }); + } + + rule.walkDecls(decl => { + // Check if the selector doesn't contain the disabled selector + // and if the value contains the rfs() function + const check = !rule.selector.includes(DISABLE_RFS_SELECTOR) && + new RegExp(`${opts.functionName}(.*)`, 'g').test(decl.value); + + if (!check) { + return; + } + + const value = rfs.value(decl.value); + const fluidValue = rfs.fluidValue(decl.value); + decl.value = value; + + if (value !== fluidValue) { + const defaultValue = opts.mode === 'min-media-query' ? (opts.class === 'enable' ? value : fluidValue) : value; + const mediaQueryValue = opts.mode === 'min-media-query' ? value : fluidValue; + decl.value = defaultValue; + + fluidRule.append(decl.clone({ value: mediaQueryValue })); + mediaQueryRules.push(fluidRule); + + // Disable classes + if (opts.class === 'disable') { + const declOpts = opts.mode === 'max-media-query' ? {} : { value }; + dcRule.append(decl.clone(declOpts)); + extraBlocks.push(dcRule); + } else if (opts.class === 'enable' && opts.mode === 'min-media-query') { + if (ecRule === undefined) { + ecRule = postcss.rule({ + selector: ruleSelector, + source: parent.source + }); + } + + ecRule.append(decl.clone({ value: fluidValue })); + extraBlocks.push(ecRule); + } + + // Remove declaration if needed + if (opts.class === 'disable' && opts.mode === 'max-media-query') { + if (decl.prev() || decl.next()) { + decl.remove(); + } else { + removeRule = true; + } + } + } + }); + + if (mediaQueryRules.length === 0) { + return; + } + + // Safari iframe resize bug: https://github.com/twbs/rfs/issues/14 + if (opts.safariIframeResizeBugFix) { + rule.append({ + prop: 'min-width', + value: '0vw' + }); + } + + const fluidMediaQuery = mediaQuery.clone(); + + for (const mediaQueryRule of mediaQueryRules) { + fluidMediaQuery.append(mediaQueryRule); + } + + parent.insertAfter(rule, fluidMediaQuery); + + if (extraBlocks.length > 0) { + for (const disableBlock of extraBlocks) { + parent.insertAfter(rule, disableBlock); + } + } + + if (removeRule) { + rule.remove(); + } + }); + }; +}; + +module.exports.postcss = true; diff --git a/node_modules/rfs/sass.sass b/node_modules/rfs/sass.sass new file mode 100644 index 00000000..62afe8ce --- /dev/null +++ b/node_modules/rfs/sass.sass @@ -0,0 +1 @@ +@import "./scss" diff --git a/node_modules/rfs/scss.scss b/node_modules/rfs/scss.scss new file mode 100644 index 00000000..aa1f82b9 --- /dev/null +++ b/node_modules/rfs/scss.scss @@ -0,0 +1,348 @@ +// stylelint-disable scss/dimension-no-non-numeric-values + +// SCSS RFS mixin +// +// Automated responsive values for font sizes, paddings, margins and much more +// +// Licensed under MIT (https://github.com/twbs/rfs/blob/main/LICENSE) + +// Configuration + +// Base value +$rfs-base-value: 1.25rem !default; +$rfs-unit: rem !default; + +@if $rfs-unit != rem and $rfs-unit != px { + @error "`#{$rfs-unit}` is not a valid unit for $rfs-unit. Use `px` or `rem`."; +} + +// Breakpoint at where values start decreasing if screen width is smaller +$rfs-breakpoint: 1200px !default; +$rfs-breakpoint-unit: px !default; + +@if $rfs-breakpoint-unit != px and $rfs-breakpoint-unit != em and $rfs-breakpoint-unit != rem { + @error "`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`."; +} + +// Resize values based on screen height and width +$rfs-two-dimensional: false !default; + +// Factor of decrease +$rfs-factor: 10 !default; + +@if type-of($rfs-factor) != number or $rfs-factor <= 1 { + @error "`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1."; +} + +// Mode. Possibilities: "min-media-query", "max-media-query" +$rfs-mode: min-media-query !default; + +// Generate enable or disable classes. Possibilities: false, "enable" or "disable" +$rfs-class: false !default; + +// 1 rem = $rfs-rem-value px +$rfs-rem-value: 16 !default; + +// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14 +$rfs-safari-iframe-resize-bug-fix: false !default; + +// Disable RFS by setting $enable-rfs to false +$enable-rfs: true !default; + +// Cache $rfs-base-value unit +$rfs-base-value-unit: unit($rfs-base-value); + +@function divide($dividend, $divisor, $precision: 10) { + $sign: if($dividend > 0 and $divisor > 0 or $dividend < 0 and $divisor < 0, 1, -1); + $dividend: abs($dividend); + $divisor: abs($divisor); + @if $dividend == 0 { + @return 0; + } + @if $divisor == 0 { + @error "Cannot divide by 0"; + } + $remainder: $dividend; + $result: 0; + $factor: 10; + @while ($remainder > 0 and $precision >= 0) { + $quotient: 0; + @while ($remainder >= $divisor) { + $remainder: $remainder - $divisor; + $quotient: $quotient + 1; + } + $result: $result * 10 + $quotient; + $factor: $factor * .1; + $remainder: $remainder * 10; + $precision: $precision - 1; + @if ($precision < 0 and $remainder >= $divisor * 5) { + $result: $result + 1; + } + } + $result: $result * $factor * $sign; + $dividend-unit: unit($dividend); + $divisor-unit: unit($divisor); + $unit-map: ( + "px": 1px, + "rem": 1rem, + "em": 1em, + "%": 1% + ); + @if ($dividend-unit != $divisor-unit and map-has-key($unit-map, $dividend-unit)) { + $result: $result * map-get($unit-map, $dividend-unit); + } + @return $result; +} + +// Remove px-unit from $rfs-base-value for calculations +@if $rfs-base-value-unit == px { + $rfs-base-value: divide($rfs-base-value, $rfs-base-value * 0 + 1); +} +@else if $rfs-base-value-unit == rem { + $rfs-base-value: divide($rfs-base-value, divide($rfs-base-value * 0 + 1, $rfs-rem-value)); +} + +// Cache $rfs-breakpoint unit to prevent multiple calls +$rfs-breakpoint-unit-cache: unit($rfs-breakpoint); + +// Remove unit from $rfs-breakpoint for calculations +@if $rfs-breakpoint-unit-cache == px { + $rfs-breakpoint: divide($rfs-breakpoint, $rfs-breakpoint * 0 + 1); +} +@else if $rfs-breakpoint-unit-cache == rem or $rfs-breakpoint-unit-cache == "em" { + $rfs-breakpoint: divide($rfs-breakpoint, divide($rfs-breakpoint * 0 + 1, $rfs-rem-value)); +} + +// Calculate the media query value +$rfs-mq-value: if($rfs-breakpoint-unit == px, #{$rfs-breakpoint}px, #{divide($rfs-breakpoint, $rfs-rem-value)}#{$rfs-breakpoint-unit}); +$rfs-mq-property-width: if($rfs-mode == max-media-query, max-width, min-width); +$rfs-mq-property-height: if($rfs-mode == max-media-query, max-height, min-height); + +// Internal mixin used to determine which media query needs to be used +@mixin _rfs-media-query { + @if $rfs-two-dimensional { + @if $rfs-mode == max-media-query { + @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}), (#{$rfs-mq-property-height}: #{$rfs-mq-value}) { + @content; + } + } + @else { + @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) and (#{$rfs-mq-property-height}: #{$rfs-mq-value}) { + @content; + } + } + } + @else { + @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) { + @content; + } + } +} + +// Internal mixin that adds disable classes to the selector if needed. +@mixin _rfs-rule { + @if $rfs-class == disable and $rfs-mode == max-media-query { + // Adding an extra class increases specificity, which prevents the media query to override the property + &, + .disable-rfs &, + &.disable-rfs { + @content; + } + } + @else if $rfs-class == enable and $rfs-mode == min-media-query { + .enable-rfs &, + &.enable-rfs { + @content; + } + } @else { + @content; + } +} + +// Internal mixin that adds enable classes to the selector if needed. +@mixin _rfs-media-query-rule { + + @if $rfs-class == enable { + @if $rfs-mode == min-media-query { + @content; + } + + @include _rfs-media-query () { + .enable-rfs &, + &.enable-rfs { + @content; + } + } + } + @else { + @if $rfs-class == disable and $rfs-mode == min-media-query { + .disable-rfs &, + &.disable-rfs { + @content; + } + } + @include _rfs-media-query () { + @content; + } + } +} + +// Helper function to get the formatted non-responsive value +@function rfs-value($values) { + // Convert to list + $values: if(type-of($values) != list, ($values,), $values); + + $val: ""; + + // Loop over each value and calculate value + @each $value in $values { + @if $value == 0 { + $val: $val + " 0"; + } + @else { + // Cache $value unit + $unit: if(type-of($value) == "number", unit($value), false); + + @if $unit == px { + // Convert to rem if needed + $val: $val + " " + if($rfs-unit == rem, #{divide($value, $value * 0 + $rfs-rem-value)}rem, $value); + } + @else if $unit == rem { + // Convert to px if needed + $val: $val + " " + if($rfs-unit == px, #{divide($value, $value * 0 + 1) * $rfs-rem-value}px, $value); + } @else { + // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value + $val: $val + " " + $value; + } + } + } + + // Remove first space + @return unquote(str-slice($val, 2)); +} + +// Helper function to get the responsive value calculated by RFS +@function rfs-fluid-value($values) { + // Convert to list + $values: if(type-of($values) != list, ($values,), $values); + + $val: ""; + + // Loop over each value and calculate value + @each $value in $values { + @if $value == 0 { + $val: $val + " 0"; + } @else { + // Cache $value unit + $unit: if(type-of($value) == "number", unit($value), false); + + // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value + @if not $unit or $unit != px and $unit != rem { + $val: $val + " " + $value; + } @else { + // Remove unit from $value for calculations + $value: divide($value, $value * 0 + if($unit == px, 1, divide(1, $rfs-rem-value))); + + // Only add the media query if the value is greater than the minimum value + @if abs($value) <= $rfs-base-value or not $enable-rfs { + $val: $val + " " + if($rfs-unit == rem, #{divide($value, $rfs-rem-value)}rem, #{$value}px); + } + @else { + // Calculate the minimum value + $value-min: $rfs-base-value + divide(abs($value) - $rfs-base-value, $rfs-factor); + + // Calculate difference between $value and the minimum value + $value-diff: abs($value) - $value-min; + + // Base value formatting + $min-width: if($rfs-unit == rem, #{divide($value-min, $rfs-rem-value)}rem, #{$value-min}px); + + // Use negative value if needed + $min-width: if($value < 0, -$min-width, $min-width); + + // Use `vmin` if two-dimensional is enabled + $variable-unit: if($rfs-two-dimensional, vmin, vw); + + // Calculate the variable width between 0 and $rfs-breakpoint + $variable-width: #{divide($value-diff * 100, $rfs-breakpoint)}#{$variable-unit}; + + // Return the calculated value + $val: $val + " calc(" + $min-width + if($value < 0, " - ", " + ") + $variable-width + ")"; + } + } + } + } + + // Remove first space + @return unquote(str-slice($val, 2)); +} + +// RFS mixin +@mixin rfs($values, $property: font-size) { + @if $values != null { + $val: rfs-value($values); + $fluid-val: rfs-fluid-value($values); + + // Do not print the media query if responsive & non-responsive values are the same + @if $val == $fluid-val { + #{$property}: $val; + } + @else { + @include _rfs-rule () { + #{$property}: if($rfs-mode == max-media-query, $val, $fluid-val); + + // Include safari iframe resize fix if needed + min-width: if($rfs-safari-iframe-resize-bug-fix, (0 * 1vw), null); + } + + @include _rfs-media-query-rule () { + #{$property}: if($rfs-mode == max-media-query, $fluid-val, $val); + } + } + } +} + +// Shorthand helper mixins +@mixin font-size($value) { + @include rfs($value); +} + +@mixin padding($value) { + @include rfs($value, padding); +} + +@mixin padding-top($value) { + @include rfs($value, padding-top); +} + +@mixin padding-right($value) { + @include rfs($value, padding-right); +} + +@mixin padding-bottom($value) { + @include rfs($value, padding-bottom); +} + +@mixin padding-left($value) { + @include rfs($value, padding-left); +} + +@mixin margin($value) { + @include rfs($value, margin); +} + +@mixin margin-top($value) { + @include rfs($value, margin-top); +} + +@mixin margin-right($value) { + @include rfs($value, margin-right); +} + +@mixin margin-bottom($value) { + @include rfs($value, margin-bottom); +} + +@mixin margin-left($value) { + @include rfs($value, margin-left); +} diff --git a/node_modules/rfs/stylus.styl b/node_modules/rfs/stylus.styl new file mode 100644 index 00000000..884cb231 --- /dev/null +++ b/node_modules/rfs/stylus.styl @@ -0,0 +1,251 @@ +// Stylus RFS mixin +// +// Automated responsive values for font sizes, paddings, margins and much more +// +// Licensed under MIT (https://github.com/twbs/rfs/blob/main/LICENSE) + +// Configuration + +// Base value +$rfs-base-value ?= 1.25rem +$rfs-unit ?= rem + +// Breakpoint at where values start decreasing if screen width is smaller +$rfs-breakpoint ?= 1200px +$rfs-breakpoint-unit ?= px + +// Resize values based on screen height and width +$rfs-two-dimensional ?= false + +// Factor of decrease +$rfs-factor ?= 10 + +// Mode. Possibilities: "min-media-query", "max-media-query" +$rfs-mode ?= "min-media-query" + +// Generate enable or disable classes. Possibilities: false, "enable" or "disable" +$rfs-class ?= false + +// 1 rem = $rfs-rem-value px +$rfs-rem-value ?= 16 + +// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14 +$rfs-safari-iframe-resize-bug-fix ?= false + +// Disable RFS by setting $enable-rfs to false +$enable-rfs ?= true + +// Cache $rfs-base-value unit +$rfs-base-value-unit = unit($rfs-base-value) + +// Remove px-unit from $rfs-base-value for calculations +if $rfs-base-value-unit == "px" + $rfs-base-value = unit($rfs-base-value, "") +else if $rfs-base-value-unit == "rem" + $rfs-base-value = unit($rfs-base-value * $rfs-rem-value, "") + +// Cache $rfs-breakpoint unit to prevent multiple calls +$rfs-breakpoint-unit-cache = unit($rfs-breakpoint) + +// Remove unit from $rfs-breakpoint for calculations +if $rfs-breakpoint-unit-cache == "px" + $rfs-breakpoint = unit($rfs-breakpoint, "") +else if $rfs-breakpoint-unit-cache == "rem" or $rfs-breakpoint-unit-cache == "em" + $rfs-breakpoint = unit($rfs-breakpoint * $rfs-rem-value, "") + +if $rfs-breakpoint-unit == px + $rfs-mq-value = unit($rfs-breakpoint, px) +else + $rfs-mq-value = unit($rfs-breakpoint / $rfs-rem-value, $rfs-breakpoint-unit) + + +if $rfs-mode == min-media-query + $rfs-mq-property-width = min-width +else + $rfs-mq-property-width = max-width + +if $rfs-mode == min-media-query + $rfs-mq-property-height = min-height +else + $rfs-mq-property-height = max-height + +_rfs-rule() + if $rfs-class == "disable" and $rfs-mode == max-media-query + &, + .disable-rfs &, + &.disable-rfs + {block} + else if $rfs-class == "enable" and $rfs-mode == min-media-query + .enable-rfs &, + &.enable-rfs + {block} + else + {block} + +_rfs-media-query-rule() + if $rfs-class == "enable" + if $rfs-mode == min-media-query + {block} + +_rfs-media-query() + .enable-rfs &, + &.enable-rfs + {block} + else + if $rfs-class == disable and $rfs-mode == min-media-query + .disable-rfs &, + &.disable-rfs + {block} + +_rfs-media-query() + {block} + +// Internal mixin used to determine which media query needs to be used +_rfs-media-query() + if $rfs-two-dimensional + if $rfs-mode == min-media-query + @media ({$rfs-mq-property-width}: $rfs-mq-value) and ({$rfs-mq-property-height}: $rfs-mq-value) + {block} + else + @media ({$rfs-mq-property-width}: $rfs-mq-value), ({$rfs-mq-property-height}: $rfs-mq-value) + {block} + else + @media ({$rfs-mq-property-width}: $rfs-mq-value) + {block} + +// Helper function to get the formatted non-responsive value +rfs-value($value) + if $value == 0 + 0 + + else if type-of($value) != "unit" + $value + else + $unit = unit($value) + + if $unit == "px" + if $rfs-unit == "rem" + unit($value / $rfs-rem-value, rem) + else + unit($value, px) + + else if $unit == "rem" + if $rfs-unit == "rem" + unit($value, rem) + else + unit($value * $rfs-rem-value, px) + else + $value + + +// Helper function to get the responsive value calculated by RFS +rfs-fluid-value($value) + if $value == 0 + 0 + else if type-of($value) != "unit" + $value + else if unit($value) != "px" and unit($value) != "rem" + $value + else + if unit($value) == "rem" + $value = unit($value * $rfs-rem-value, "") + else + $value = unit($value, "") + + // Only add the media query if the value is greater than the minimum value + if abs($value) <= $rfs-base-value or !$enable-rfs + if $rfs-unit == "rem" + unit($value / $rfs-rem-value, rem) + else + unit($value, px) + else + // Calculate the minimum value + $value-min = $rfs-base-value + (abs($value) - $rfs-base-value) / $rfs-factor; + + // Calculate difference between $value and the minimum value + $value-diff = abs($value) - $value-min; + + // Base value formatting + if $rfs-unit == rem + $min-width = unit($value-min / $rfs-rem-value, rem) + else + $min-width = unit($value-min, px) + + // Use `vmin` if two-dimensional is enabled + if $rfs-two-dimensional + $variable-unit = vmin + else + $variable-unit = vw + + // Calculate the variable width between 0 and $rfs-breakpoint + $variable-width = unit(round($value-diff * 100) / $rfs-breakpoint, $variable-unit) + + // Return the calculated value + if $value != abs($value) + unquote("calc(-" + $min-width + " - " + $variable-width + ")") + else + unquote("calc(" + $min-width + " + " + $variable-width + ")") + +// RFS mixin +rfs($values, $property = font-size) + $val = '' + $fluidVal = '' + + // Loop over each value and calculate responsive & non-responsive values + for $value in $values + $val+= ' ' + rfs-value($value) + $fluidVal+= ' ' + rfs-fluid-value($value) + + // Remove first space + $val = unquote(slice($val, 1)) + $fluidVal = unquote(slice($fluidVal, 1)) + + // Do not print the media query if responsive & non-responsive values are the same + if $val == $fluidVal + {$property}: $val + else + +_rfs-rule() + if $rfs-mode == "min-media-query" + {$property}: $fluidVal + else + {$property}: $val + + if $rfs-safari-iframe-resize-bug-fix and $rfs-mode == "min-media-query" + min-width: 0vw + + +_rfs-media-query-rule() + if $rfs-mode == "min-media-query" + {$property}: $val + else + {$property}: $fluidVal + +rfs-font-size($value) + rfs($value) + +rfs-padding($value, $property = padding) + rfs($value, $property) + +rfs-padding-top($value, $property = padding-top) + rfs($value, $property) + +rfs-padding-right($value, $property = padding-right) + rfs($value, $property) + +rfs-padding-bottom($value, $property = padding-bottom) + rfs($value, $property) + +rfs-padding-left($value, $property = padding-left) + rfs($value, $property) + +rfs-margin($value, $property = margin) + rfs($value, $property) + +rfs-margin-top($value, $property = margin-top) + rfs($value, $property) + +rfs-margin-right($value, $property = margin-right) + rfs($value, $property) + +rfs-margin-bottom($value, $property = margin-bottom) + rfs($value, $property) + +rfs-margin-left($value, $property = margin-left) + rfs($value, $property) diff --git a/package-lock.json b/package-lock.json index f69a67da..e4844416 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "license": "MIT", "dependencies": { "@popperjs/core": "^2.11.8", - "bootstrap": "^5.3.3" + "bootstrap": "^5.3.3", + "rfs": "^10.0.0" }, "devDependencies": { "@babel/core": "^7.24.7", @@ -9919,7 +9920,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, "license": "MIT" }, "node_modules/pretty-ms": { @@ -10243,6 +10243,18 @@ "node": ">=0.10.0" } }, + "node_modules/rfs": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/rfs/-/rfs-10.0.0.tgz", + "integrity": "sha512-Iu0N8fGAHDE6NZSc+S1aaY9ClaqkOdko+NvAstUS5sxRnzUgV20Ak0cOsMEP/vyYdzM3DOUOPKXH4XhfzMthvw==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/rollup": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", diff --git a/package.json b/package.json index 7d4835f3..163478ed 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ }, "dependencies": { "@popperjs/core": "^2.11.8", - "bootstrap": "^5.3.3" + "bootstrap": "^5.3.3", + "rfs": "^10.0.0" }, "devDependencies": { "@babel/core": "^7.24.7",