From ff6a49387e901d22d405b5913cf14ba8163c3b97 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Wed, 17 Sep 2025 13:08:53 +0200 Subject: [PATCH 1/2] Remove lodash dependencies Replace lodash.merge, lodash.castarray, and lodash.isplainobject with inline implementations to reduce bundle size and eliminate external dependencies. The merge function maintains full compatibility with lodash behavior, including recursive merging of nested objects within arrays. - Remove lodash.merge, lodash.castarray, lodash.isplainobject from dependencies - Add inline implementations in src/utils.js with identical behavior - Update src/index.js to import utilities from utils module - Maintain backward compatibility and all existing functionality Fixes bundle size concerns raised in community discussions about lodash dependencies. --- package-lock.json | 39 +++-------------------------- package.json | 3 --- src/index.js | 9 ++----- src/utils.js | 62 +++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 65 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index 001b8a5..7ac3cc3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,14 @@ { "name": "@tailwindcss/typography", - "version": "0.5.14", + "version": "0.5.16", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@tailwindcss/typography", - "version": "0.5.14", + "version": "0.5.16", "license": "MIT", "dependencies": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "devDependencies": { @@ -30,7 +27,7 @@ "tailwindcss": "^3.2.2" }, "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders" + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "node_modules/@ampproject/remapping": { @@ -5293,21 +5290,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -11025,21 +11007,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", diff --git a/package.json b/package.json index 70ff5f3..ff656ab 100644 --- a/package.json +++ b/package.json @@ -48,9 +48,6 @@ "tailwindcss": "^3.2.2" }, "dependencies": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "jest": { diff --git a/src/index.js b/src/index.js index 04830b9..d231d01 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,6 @@ const plugin = require('tailwindcss/plugin') -const merge = require('lodash.merge') -const castArray = require('lodash.castarray') const styles = require('./styles') -const { commonTrailingPseudos } = require('./utils') +const { commonTrailingPseudos, isObject, isPlainObject, merge, castArray } = require('./utils') const computed = { // Reserved for future "magic properties", for example: @@ -25,10 +23,6 @@ function inWhere(selector, { className, modifier, prefix }) { return `:where(${selectorPrefix}${selector}):not(:where([class~="${prefixedNot}"],[class~="${prefixedNot}"] *))` } -function isObject(value) { - return typeof value === 'object' && value !== null -} - function configToCss(config = {}, { target, className, modifier, prefix }) { function updateSelector(k, v) { if (target === 'legacy') { @@ -138,3 +132,4 @@ module.exports = plugin.withOptions( } } ) + diff --git a/src/utils.js b/src/utils.js index 5350890..2faa03e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,9 +1,67 @@ -const isPlainObject = require('lodash.isplainobject') - const parser = require('postcss-selector-parser') const parseSelector = parser() +function isObject(value) { + return typeof value === 'object' && value !== null +} + +function isPlainObject(value) { + if (typeof value !== 'object' || value === null) { + return false + } + + if (Object.prototype.toString.call(value) !== '[object Object]') { + return false + } + + if (Object.getPrototypeOf(value) === null) { + return true + } + + let proto = value + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto) + } + + return Object.getPrototypeOf(value) === proto +} + +function merge(target, ...sources) { + if (!sources.length) return target + const source = sources.shift() + + if (isObject(target) && isObject(source)) { + for (const key in source) { + if (Array.isArray(source[key])) { + if (!target[key]) target[key] = [] + source[key].forEach((item, index) => { + if (isPlainObject(item) && isPlainObject(target[key][index])) { + target[key][index] = merge(target[key][index], item) + } else { + target[key][index] = item + } + }) + } else if (isPlainObject(source[key])) { + if (!target[key]) target[key] = {} + merge(target[key], source[key]) + } else { + target[key] = source[key] + } + } + } + + return merge(target, ...sources) +} + +function castArray(value) { + return Array.isArray(value) ? value : [value] +} + module.exports = { + isObject, + isPlainObject, + merge, + castArray, isUsableColor(color, values) { return isPlainObject(values) && color !== 'gray' && values[600] }, From fb0d2420af8f29ba2eaeb6158fe1edbed7c64500 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Wed, 17 Sep 2025 15:59:31 +0200 Subject: [PATCH 2/2] Add changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29493f2..bba3064 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Include unit in `hr` border-width value ([#379](https://github.com/tailwindlabs/tailwindcss-typography/pull/379) +### Changed + +- Remove lodash dependencies ([#402](https://github.com/tailwindlabs/tailwindcss-typography/pull/402)) + ## [0.5.16] - 2025-01-07 ### Fixed