diff --git a/Makefile b/Makefile index 741bc7bfbb..8d79ec9df1 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,22 @@ -.PHONY: build -build: +.PHONY: clean +clean: rm -rf ./dist + +# A full build from scratch. Use this for CI and for publishing. +.PHONY: build +build: clean build-incremental + +# Rebuilds only the parts whose sources changed. Compiling the stylesheets takes +# minutes while the JavaScript takes seconds, so a watch rebuild should not +# redo the stylesheets on every component edit. +.PHONY: build-incremental +build-incremental: build-js build-scss + +.PHONY: build-js +build-js: tsc --project tsconfig.build.json rm icons/es5/index.d.ts # We don't need this; not sure how to tell tsc not to generate it - ./node_modules/.bin/babel src --config-file ./babel.config.json --out-dir dist --source-maps --ignore **/*.d.ts,**/*.test.jsx,**/*.test.tsx,**/__mocks__,**/__snapshots__,**/setupTest.js --copy-files --extensions ".ts,.tsx,.jsx" + babel src --config-file ./babel.config.json --out-dir dist --source-maps --ignore **/*.d.ts,**/*.test.jsx,**/*.test.tsx,**/__mocks__,**/__snapshots__,**/setupTest.js --copy-files --extensions ".ts,.tsx,.jsx" # --copy-files will bring in everything else that wasn't processed by babel. Remove what we don't want. find ./dist -name "tests" -type d -prune -exec rm -rf "{}" \; # delete tests directories find ./dist -name "*.test.*" -delete # delete other tests files that weren't in tests directories @@ -11,6 +24,13 @@ build: rm -rf dist/**/__snapshots__ rm -rf dist/__mocks__ rm -rf dist/setupTest.js + +THEME_SOURCES := $(shell find styles/scss styles/css src \( -name '*.scss' -o -name '*.css' \)) + +.PHONY: build-scss +build-scss: dist/theme-urls.json + +dist/theme-urls.json: $(THEME_SOURCES) lib/build-scss.js ./bin/paragon-scripts.js build-scss NPM_TESTS=build i18n_extract lint test diff --git a/lib/build-scss.js b/lib/build-scss.js index 4d297d8bed..fcdd9a1321 100755 --- a/lib/build-scss.js +++ b/lib/build-scss.js @@ -90,7 +90,12 @@ const compileAndWriteStyleSheets = ({ if (!url.startsWith('~')) { return null; } - return new URL(url.substring(1), `${pathToFileURL('node_modules')}/node_modules`); + const specifier = url.substring(1); + // The package name is an optional '@scope/' prefix followed by one more path segment. + const packageName = specifier.match(/^(?:@[^/]+\/)?[^/]+/)[0]; + const searchPaths = require.resolve.paths(packageName) || []; + const dir = searchPaths.find((nodeModules) => fs.existsSync(path.join(nodeModules, packageName))); + return dir ? pathToFileURL(path.join(dir, specifier)) : null; }, }], // For now we can't resolve these warnings as we need to upgrade our 'bootstrap' dependency to do so: diff --git a/nodemon.json b/nodemon.json new file mode 100644 index 0000000000..5703315f98 --- /dev/null +++ b/nodemon.json @@ -0,0 +1,18 @@ +{ + "watch": [ + "src", + "styles", + "tokens", + "lib", + "bin" + ], + "ext": "ts,tsx,js,jsx,json,scss,css", + "ignore": [ + "node_modules/**", + ".git/**", + "dist/**", + "**/*.test.*", + "**/__snapshots__/**" + ], + "delay": 250 +} diff --git a/package-lock.json b/package-lock.json index e2c26a8991..998997b518 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@openedx/paragon", - "version": "20.18.1", + "version": "0.0.0-dev", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@openedx/paragon", - "version": "20.18.1", + "version": "0.0.0-dev", "license": "Apache-2.0", "workspaces": [ "example", @@ -85,7 +85,6 @@ "@types/jest": "^29.5.10", "@types/react": "^18", "@types/react-dom": "^18", - "@types/react-responsive": "^9.0.0", "@types/react-table": "^7.7.19", "@types/react-test-renderer": "^18.0.0", "@types/uuid": "^9.0.0", @@ -106,6 +105,7 @@ "jest-cli": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "markdown-loader-jest": "^0.1.1", + "nodemon": "^3.1.14", "react": "^18", "react-intl": "^10.1.20", "react-test-renderer": "^18", @@ -12229,17 +12229,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-responsive": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/react-responsive/-/react-responsive-9.0.0.tgz", - "integrity": "sha512-2B/tmI2OE5Ul57/yo6szbTmI6rbWus6K317lk6baf6Ngvs1RPfvwerns+c0FtmoIDaK7wwVGllZjTTrpYfW2fA==", - "deprecated": "This is a stub types definition. react-responsive provides its own type definitions, so you do not need this installed.", - "dev": true, - "license": "MIT", - "dependencies": { - "react-responsive": "*" - } - }, "node_modules/@types/react-table": { "version": "7.7.20", "resolved": "https://registry.npmjs.org/@types/react-table/-/react-table-7.7.20.tgz", @@ -27054,6 +27043,13 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, "node_modules/image-minimizer-webpack-plugin": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/image-minimizer-webpack-plugin/-/image-minimizer-webpack-plugin-4.1.4.tgz", @@ -33100,6 +33096,110 @@ "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", "license": "MIT" }, + "node_modules/nodemon": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -38305,6 +38405,13 @@ "url": "https://github.com/sponsors/lupomontero" } }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, "node_modules/pubsub-js": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/pubsub-js/-/pubsub-js-1.9.5.tgz", @@ -43701,6 +43808,32 @@ "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", "license": "MIT" }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sirv": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", @@ -46132,6 +46265,16 @@ "node": ">=6" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -46798,6 +46941,13 @@ "react": ">=15.0.0" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, "node_modules/undici": { "version": "7.25.0", "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz", diff --git a/package.json b/package.json index 2445976060..5deae08310 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@openedx/paragon", - "version": "20.18.1", + "version": "0.0.0-dev", "description": "Accessible, responsive UI component library based on Bootstrap.", "main": "dist/index.js", "module": "dist/index.js", @@ -30,6 +30,9 @@ }, "scripts": { "build": "make build", + "build-incremental": "make build-incremental", + "clean": "make clean", + "watch:build": "nodemon -x \"npm run build-incremental\"", "build-docs": "make build-docs", "commit": "commit", "debug-test": "node --inspect-brk node_modules/.bin/jest --runInBand --coverage", @@ -133,7 +136,6 @@ "@types/jest": "^29.5.10", "@types/react": "^18", "@types/react-dom": "^18", - "@types/react-responsive": "^9.0.0", "@types/react-table": "^7.7.19", "@types/react-test-renderer": "^18.0.0", "@types/uuid": "^9.0.0", @@ -154,6 +156,7 @@ "jest-cli": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "markdown-loader-jest": "^0.1.1", + "nodemon": "^3.1.14", "react": "^18", "react-intl": "^10.1.20", "react-test-renderer": "^18",