Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3c04fed
Webpack 5 related changes
andreas-schultz Aug 26, 2026
c6c878c
Merge branch 'develop' into feature/webpackUpgrade-CMEM-6650
andreas-schultz Aug 26, 2026
b0c5c2d
upgrade storybook libs
haschek Aug 27, 2026
cbf9bd8
upgrade jest related libs
haschek Aug 27, 2026
f75709e
upgrade eslint related libs
haschek Aug 27, 2026
32b9406
upgrade stylelint related libs
haschek Aug 27, 2026
5fee271
upgrade sass library
haschek Aug 27, 2026
1b6ef91
upgrade yargs library
haschek Aug 27, 2026
90ec3b0
upgrade babel libraries, remove unnessecary parts of it
haschek Aug 27, 2026
3c706b2
upgrade prettier library
haschek Aug 27, 2026
3ab137c
upgrade other dev libs
haschek Aug 27, 2026
585dc56
upgrade carbon libraries
haschek Aug 27, 2026
1368fd2
upgrade codemirror libs
haschek Aug 27, 2026
564379b
upgrade other dependencies
haschek Aug 27, 2026
8d60c41
update resolutions configuration after library upgrades
haschek Aug 27, 2026
0802ae0
update changelog
haschek Aug 31, 2026
fef75bd
add workaround for problem of BOM selector within compressed styöesheets
haschek Aug 31, 2026
60002e8
update changelog
haschek Aug 31, 2026
9529b63
Merge pull request #421 from eccenca/bugfix/workaroundBomSelector-CME…
haschek Aug 31, 2026
0b1e16a
Merge branch 'develop' into feature/webpackUpgrade-CMEM-6650
haschek Sep 1, 2026
f358d19
switch engines info back to former value because it is meant for cons…
haschek Sep 1, 2026
65db322
fix Storybook implication with existing /dist filder, and cirrect the…
haschek Sep 1, 2026
a654149
update changelog re assert inclusion
haschek Sep 1, 2026
d3a06fc
fix includePaths, so it works also if they would not have the same
haschek Sep 1, 2026
907ef48
Merge branch 'feature/maintainLibraries-CMEM-8066' into test/mergeMai…
haschek Sep 1, 2026
b7e1776
set engines.node to 18.19
haschek Sep 2, 2026
d00253a
improve error handling
haschek Sep 2, 2026
d8a8498
fix import detection
haschek Sep 2, 2026
0474b1b
harden the includePaths resolver
haschek Sep 2, 2026
9f78af8
istall explitely util along assert
haschek Sep 2, 2026
bb89d8a
Merge branch 'feature/webpackUpgrade-CMEM-6650' into feature/webpackM…
haschek Sep 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lts/krypton
50 changes: 31 additions & 19 deletions .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const sass = require("sass");
const path = require("path");
const sass = require("sass");
const sassRenderSyncConfig = require("./../scripts/sassConfig");
const { silenceDeprecations } = require("../scripts/sassDeprecationConfig");

Expand All @@ -9,15 +9,6 @@ module.exports = {
"@storybook/addon-links",
"@storybook/addon-docs",
"@storybook/addon-a11y",
{
name: "@storybook/preset-scss",
options: {
sassLoaderOptions: {
implementation: sass,
sassOptions: {...sassRenderSyncConfig, silenceDeprecations},
},
},
},
"@storybook/addon-webpack5-compiler-babel",
],
framework: {
Expand Down Expand Up @@ -64,6 +55,16 @@ module.exports = {
},
},
webpackFinal: async (config, { configType }) => {
// never let the compiled package output take part in the Storybook build,
// stories always have to use the sources
// a directory import like `"./../../../../"` is resolved by the `exports` field of our
// own package.json and would silently pull `dist/esm/` into the preview bundle,
// this restriction removes it from the candidates so that the root `index.ts` is used
const distPath = path.resolve(__dirname, "..", "dist");
config.resolve.restrictions = [
...(config.resolve.restrictions ?? []),
new RegExp(`^(?!${distPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[/\\\\])`),
];
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
if (configType === "PRODUCTION") {
// remove source maps from production storybook
Expand All @@ -72,13 +73,29 @@ module.exports = {
config.devtool = false;
}
config.module.rules = [
{
test: /\.s[ac]ss$/i,
use: [
require.resolve("style-loader"),
{
loader: require.resolve("css-loader"),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve("sass-loader"),
options: {
implementation: sass,
sassOptions: { ...sassRenderSyncConfig, silenceDeprecations },
},
},
],
},
{
test: /\.(png|jpg|gif|svg)(\\?.*)?$/,
include: /\.tobase64\./,
loader: "url-loader",
options: {
limit: true,
},
type: "asset/inline",
},
...config.module.rules.map((rule) => {
if (
Expand All @@ -92,11 +109,6 @@ module.exports = {
return rule;
}),
];
config.resolve.alias = {
...config.resolve.alias,
// Fix nasty bug with importing from this package, Storybook webpack cannot resolve it otherwise
"@codemirror/legacy-modes": path.resolve(__dirname, "../node_modules/@codemirror/legacy-modes"),
};
return config;
},
};
2 changes: 1 addition & 1 deletion .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const parameters = {
const preview = {
// Enables auto-generated documentation for all stories
// @see https://storybook.js.org/docs/writing-docs/autodocs
tags: ['autodocs'],
tags: ["autodocs"],
parameters,
};

Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,27 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- `<Switch />`
- `noDrag` parameter: Add the `nodrag` class to the Switch element. Default: `true`

### Changed

- Upgrading base libraries
- Carbon, Codemirror, React-Flow
- minimum node version (`engines.node`) is `18.19.0` now
- the build of the ESM distribution needs a synchronous `import.meta.resolve`, which is only available since this version

### Fixed

- `<PropertyValuePair />`
- fix description and story to point out that `PropertyValueList` need always to be used as wrapper
- BOM issue on compressed stylesheet
- first rule `selector` becomes `BOM:selector` that is valid but will never apply
- we fixed this problem by adding a dummy rule as first rule
- ESM distribution
- the imports of the `@codemirror/legacy-modes` modes were written with an additional `.js` suffix, but the `exports` map of this package only provides the extension-less sub paths, so they were expanded to unresolvable paths like `mode/jinja2.js.js`
- Storybook
- the `<Tab />` story imported the package root directory, this way the `exports` field of our own `package.json` pulled the built `dist/esm/` output into the preview bundle instead of the sources, and the Storybook build failed as soon as `dist/` existed
- the webpack configuration excludes `dist/` from module resolution now, so the sources are always used even if a story references the package root
- Added explicitly `assert` dependency
- the linter of `<CodeEditor />` uses `jshint`, which imports `console-browserify`, and this package requires the node core modules `assert` and `util` without declaring them; bundlers based on webpack 5 do not provide shims for node core modules anymore, so the polyfill (and `util` together with it) is part of the delivery now

### Deprecated

Expand Down
7 changes: 1 addition & 6 deletions babel.config.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript", "@babel/preset-flow"],
"plugins": [
["@babel/plugin-transform-private-methods", { "loose": true }],
["@babel/plugin-transform-private-property-in-object", { "loose": true }],
["@babel/plugin-transform-class-properties", { "loose": true }]
]
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"]
}
93 changes: 40 additions & 53 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"registry": "https://registry.npmjs.org"
},
"engines": {
"node": ">=18.18.0"
"node": ">=18.19.0"
},
"style": "src/index.scss",
"main": "dist/cjs/index.js",
Expand Down Expand Up @@ -71,18 +71,19 @@
"@blueprintjs/colors": "^5.1.16",
"@blueprintjs/core": "6.8.1",
"@blueprintjs/select": "6.1.1",
"@carbon/icons": "^11.80.0",
"@carbon/react": "^1.107.1",
"@codemirror/lang-html": "^6.4.11",
"@carbon/icons": "^11.87.0",
"@carbon/react": "^1.115.0",
"@codemirror/lang-html": "^6.4.12",
"@codemirror/lang-javascript": "^6.2.5",
"@codemirror/lang-json": "^6.0.2",
"@codemirror/lang-markdown": "^6.5.0",
"@codemirror/lang-markdown": "^6.5.2",
"@codemirror/lang-sql": "^6.10.0",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/lang-yaml": "^6.1.3",
"@codemirror/legacy-modes": "^6.5.2",
"@codemirror/legacy-modes": "^6.5.3",
"@mavrin/remark-typograf": "^2.2.0",
"@xyflow/react": "^12.9.3",
"@xyflow/react": "^12.11.5",
"assert": "^2.1.0",
"classnames": "^2.5.1",
"codemirror": "^6.0.2",
"color": "^5.0.3",
Expand All @@ -95,7 +96,7 @@
"react": "^18.2.0",
"react-dom": "^18.3.1",
"react-flow-renderer": "9.7.4",
"react-inlinesvg": "^4.4.1",
"react-inlinesvg": "^4.5.0",
"react-is": "^18.3.1",
"react-markdown": "^10.1.0",
"react-syntax-highlighter": "^16.1.1",
Expand All @@ -106,95 +107,82 @@
"remark-parse": "^11.0.0",
"reset-css": "^5.0.2",
"unified": "^11.0.5",
"util": "^0.12.5",
"wicg-inert": "^3.1.3"
},
"devDependencies": {
"@babel/core": "^7.29.0",
"@babel/plugin-transform-class-properties": "^7.28.6",
"@babel/plugin-transform-private-methods": "^7.28.6",
"@babel/plugin-transform-private-property-in-object": "^7.28.6",
"@babel/preset-env": "^7.29.5",
"@babel/preset-flow": "^7.27.1",
"@babel/preset-react": "^7.28.5",
"@babel/preset-typescript": "^7.28.5",
"@babel/core": "^7.29.7",
"@babel/preset-env": "^7.29.7",
"@babel/preset-react": "^7.29.7",
"@babel/preset-typescript": "^7.29.7",
"@eslint/compat": "^2.1.0",
"@eslint/eslintrc": "^3.3.5",
"@eslint/eslintrc": "^3.3.6",
"@eslint/js": "^10.0.1",
"@storybook/addon-a11y": "^10.4.0",
"@storybook/addon-docs": "^10.4.0",
"@storybook/addon-links": "^10.4.0",
"@storybook/addon-a11y": "^10.5.10",
"@storybook/addon-docs": "^10.5.10",
"@storybook/addon-links": "^10.5.10",
"@storybook/addon-webpack5-compiler-babel": "^4.0.1",
"@storybook/cli": "^10.4.0",
"@storybook/preset-scss": "^1.0.3",
"@storybook/react": "^10.4.0",
"@storybook/react-webpack5": "^10.4.0",
"@storybook/cli": "^10.5.10",
"@storybook/react": "^10.5.10",
"@storybook/react-webpack5": "^10.5.10",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^16.3.2",
"@types/he": "^1.2.3",
"@types/jest": "^30.0.0",
"@types/jshint": "^2.12.4",
"@types/lodash": "^4.17.24",
"@types/lodash": "^4.17.25",
"@types/n3": "^1.26.1",
"@types/react-dom": "^18.3.7",
"@types/react-is": "^19.2.0",
"@types/react-syntax-highlighter": "^15.5.13",
"@typescript-eslint/eslint-plugin": "^8.59.3",
"@typescript-eslint/parser": "^8.59.3",
"@typescript-eslint/eslint-plugin": "^8.68.0",
"@typescript-eslint/parser": "^8.68.0",
"babel-jest": "^30.4.1",
"chromatic": "^16.10.1",
"eslint": "^10.3.0",
"chromatic": "^18.6.1",
"css-loader": "^7.1.4",
"eslint": "^10.9.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-simple-import-sort": "^13.0.0",
"eslint-plugin-simple-import-sort": "^14.0.0",
"husky": "^4.3.8",
"identity-obj-proxy": "^3.0.0",
"jest": "^30.4.2",
"jest-environment-jsdom": "^30.4.1",
"jest-fixed-jsdom": "^0.0.11",
"jest-pnp-resolver": "^1.2.3",
"lint-staged": "^15.5.2",
"node-sass-package-importer": "^5.3.3",
"path": "^0.12.7",
"prettier": "^3.8.3",
"prettier": "^3.9.6",
"react-app-polyfill": "^3.0.0",
"react-lorem-ipsum": "^1.4.9",
"regenerator-runtime": "^0.14.1",
"rimraf": "^6.1.3",
"sass": "^1.99.0",
"sass-loader": "^16.0.8",
"storybook": "^10.4.0",
"stylelint": "^17.11.0",
"stylelint-config-recess-order": "^7.7.0",
"sass": "^1.103.1",
"sass-loader": "^17.0.0",
"storybook": "^10.5.10",
"style-loader": "^4.0.0",
"stylelint": "^17.14.1",
"stylelint-config-recess-order": "^7.8.0",
"stylelint-config-standard-scss": "^17.0.0",
"stylelint-order": "^8.1.1",
"ts-node": "^10.9.2",
"tsc-esm-fix": "^3.1.2",
"typescript": "^5.9.3",
"url-loader": "^4.1.1",
"yargs": "^18.0.0"
"webpack": "^5.109.2",
"yargs": "^18.1.0"
},
"peerDependencies": {
"@blueprintjs/core": ">=6",
"react": ">=18"
},
"resolutions": {
"**/@blueprintjs/core": "6.8.1",
"node-sass-package-importer/**/postcss": "^8.5.18",
"stylelint-order/**/postcss": "^8.5.12",
"stylelint/**/postcss": "^8.5.18",
"hast-util-from-parse5": "8.0.0",
"**/lodash": "^4.18.1",
"**/minimatch": "^3.1.4",
"**/serialize-javascript": "^7.0.5",
"**/ws": "^8.21.0",
"babel-jest/**/js-yaml": "^3.15.1",
"stylelint/**/js-yaml": "^4.3.1",
"@eslint/eslintrc/**/js-yaml": "^4.3.1",
"**/nanoid": "^3.3.18",
"**/fast-uri": "^3.1.3",
"sass/**/immutable": "^5.1.8",
"**/brace-expansion": "^1.1.18"
"**/postcss": "^8.5.18",
"**/serialize-javascript": "^7.0.5"
},
"husky": {
"hooks": {
Expand Down Expand Up @@ -225,7 +213,6 @@
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.d.ts"
],
"resolver": "jest-pnp-resolver",
"setupFiles": [
"react-app-polyfill/jsdom"
],
Expand Down
49 changes: 46 additions & 3 deletions scripts/compile-sass.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,63 @@
import * as fs from "fs";
import tildeImporter from "node-sass-package-importer";
import * as path from "path";
import * as sass from "sass";
import yargs from "yargs";

import sassRenderSyncConfig from "./sassConfig";
import { silenceDeprecations } from "./sassDeprecationConfig"
import { silenceDeprecations } from "./sassDeprecationConfig";

const args = yargs(process.argv.slice(2)).argv as any;

/**
* Returns the directory a package was installed into, or `undefined` if it cannot be found.
* The `node_modules` chain of the resolver is walked directly instead of resolving the
* `package.json` of the package, because a package is free to hide that file behind its
* `exports` map, which would let `require.resolve()` fail with `ERR_PACKAGE_PATH_NOT_EXPORTED`.
* Symbolic links are resolved, so that the real location is used, e.g. the store directory of pnpm.
*/
const packageDirectory = (packageName: string) => {
for (const searchPath of require.resolve.paths(packageName) ?? []) {
const candidate = path.join(searchPath, ...packageName.split("/"));
if (fs.existsSync(path.join(candidate, "package.json"))) return fs.realpathSync(candidate);
}
return undefined;
};

/**
* Returns the dependency root a package was installed into, i.e. the `node_modules` directory
* holding it. The number of levels to climb is taken from the package name, this way scoped
* (`@scope/name`) and plain (`name`) packages are both handled correctly.
*/
const dependencyRoot = (packageName: string) => {
const directory = packageDirectory(packageName);
return directory === undefined ? undefined : path.resolve(directory, ...packageName.split("/").map(() => ".."));
};

// Imports without tilde syntax are not handled by the importer below, sass resolves them relative
// to the importing file and via these include paths. `@blueprintjs/core` and `@carbon/react` both
// use them internally to reach their sibling packages, e.g. `@blueprintjs/colors` or
// `@carbon/styles`. Their dependency roots are looked up separately because the packages do not
// need to share one, e.g. if only one of them is hoisted into a parent workspace. The local
// `node_modules` is kept as a fallback, it is also used alone if a dependency root cannot be
// determined. All paths are absolute, so that duplicates of the same directory can be removed.
const includePaths = [
...new Set(
[dependencyRoot("@blueprintjs/core"), dependencyRoot("@carbon/react"), path.resolve("node_modules")].filter(
(includePath): includePath is string => includePath !== undefined,
),
),
];

const styles = sass.renderSync({
importer: tildeImporter(),
...sassRenderSyncConfig,
silenceDeprecations: silenceDeprecations as sass.DeprecationOrId[],
silenceDeprecations: [...silenceDeprecations, "legacy-js-api"] as sass.DeprecationOrId[],
file: "src/index.scss",
includePaths: ["node_modules"], // Carbon does not use tilde import syntax
includePaths,
});

if (args.outputCss) {
// eslint-disable-next-line no-console
console.log(styles.css.toString());
}
5 changes: 5 additions & 0 deletions scripts/fix-esm-dist
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
#!/bin/sh
# abort as soon as one of the steps fails, otherwise a broken ESM output would be
# reported as a successful build because the exit code of the last command wins
set -e
yarn tsc-esm-fix --target='dist/esm'
node ./scripts/fix-esm-imports.mjs dist/esm
cat >dist/esm/package.json <<!EOF
{
"type": "module"
Expand Down
Loading
Loading