diff --git a/.changeset/early-kiwis-arrive.md b/.changeset/early-kiwis-arrive.md new file mode 100644 index 00000000..db701635 --- /dev/null +++ b/.changeset/early-kiwis-arrive.md @@ -0,0 +1,6 @@ +--- +"10up-toolkit": minor +"tenup-theme": minor +--- + +Add support for `scriptModule` & `viewScriptModule` assets diff --git a/package-lock.json b/package-lock.json index dff7da64..cddbc405 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,68 +25,30 @@ "link": true }, "node_modules/@10up/block-components": { - "version": "1.7.0", - "license": "GPL-2.0-or-later", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@10up/block-components/-/block-components-1.18.0.tgz", + "integrity": "sha512-pp+bDDJ1ewC8TwLGgM3aFaNA/X6/t03eRDiTLgAjVIp6j3f1cF5DnU98lK/xoTDPQJP+erQy6U0r+FoZm0O8GA==", + "workspaces": [ + "./", + "example/" + ], "dependencies": { - "@emotion/react": "^11.1.5", - "@emotion/styled": "^11.0.0", - "@wordpress/icons": "^6.1.1", + "@10up/block-components": "^1.17.2", + "@dnd-kit/core": "^6.0.6", + "@dnd-kit/modifiers": "^6.0.1", + "@dnd-kit/sortable": "^7.0.1", + "@dnd-kit/utilities": "^3.2.1", + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "@floating-ui/react-dom": "^1.0.1", + "@leeoniya/ufuzzy": "^1.0.8", + "@wordpress/icons": "^9.14.0", "array-move": "^3.0.1", - "prop-types": "^15.7.2", - "react-sortable-hoc": "^1.11.0", + "prop-types": "^15.8.1", + "react-window": "^1.8.9", "uuid": "^8.3.2" } }, - "node_modules/@10up/block-components/node_modules/react": { - "version": "16.14.0", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@10up/block-components/node_modules/react-dom": { - "version": "16.14.0", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/@10up/block-components/node_modules/react-sortable-hoc": { - "version": "1.11.0", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.2.0", - "invariant": "^2.2.4", - "prop-types": "^15.5.7" - }, - "peerDependencies": { - "prop-types": "^15.5.7", - "react": "^0.14.0 || ^15.0.0 || ^16.0.0", - "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@10up/block-components/node_modules/scheduler": { - "version": "0.19.1", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/@10up/component-accordion": { "resolved": "projects/library", "link": true @@ -2927,6 +2889,68 @@ "node": ">=10.0.0" } }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.0.tgz", + "integrity": "sha512-ea7IkhKvlJUv9iSHJOnxinBcoOI3ppGnnL+VDJ75O45Nss6HtZd8IdN8touXPDtASfeI2T2LImb8VOZcL47wjQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.1.0.tgz", + "integrity": "sha512-J3cQBClB4TVxwGo3KEjssGEXNJqGVWx17aRTZ1ob0FliR5IjYgTxl5YJbKTzA6IzrtelotH19v6y7uoIRUZPSg==", + "dependencies": { + "@dnd-kit/accessibility": "^3.1.0", + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/modifiers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-6.0.1.tgz", + "integrity": "sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A==", + "dependencies": { + "@dnd-kit/utilities": "^3.2.1", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.0.6", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.2.tgz", + "integrity": "sha512-wDkBHHf9iCi1veM834Gbk1429bd4lHX4RpAwT0y2cHLf246GAvU2sVw/oxWNpPKQNQRQaeGXhAVgrOl1IT+iyA==", + "dependencies": { + "@dnd-kit/utilities": "^3.2.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.0.7", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", + "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", "license": "MIT", @@ -3186,6 +3210,40 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", + "dependencies": { + "@floating-ui/utils": "^0.2.1" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-1.3.0.tgz", + "integrity": "sha512-htwHm67Ji5E/pROEAr7f8IKFShuiCKHwUC/UY4vC3I5jiSvGFAYnSYiZO5MlGmads+QqvUkR9ANHEguGrDv72g==", + "dependencies": { + "@floating-ui/dom": "^1.2.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "license": "Apache-2.0", @@ -4270,6 +4328,11 @@ "dev": true, "license": "MIT" }, + "node_modules/@leeoniya/ufuzzy": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@leeoniya/ufuzzy/-/ufuzzy-1.0.14.tgz", + "integrity": "sha512-/xF4baYuCQMo+L/fMSUrZnibcu0BquEGnbxfVPiZhs/NbJeKj4c/UmFpQzW9Us0w45ui/yYW3vyaqawhNYsTzA==" + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "license": "MIT" @@ -5889,6 +5952,7 @@ }, "node_modules/@types/react": { "version": "17.0.74", + "dev": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -5898,6 +5962,7 @@ }, "node_modules/@types/react-dom": { "version": "17.0.25", + "dev": true, "license": "MIT", "dependencies": { "@types/react": "^17" @@ -6444,21 +6509,22 @@ } }, "node_modules/@wordpress/dependency-extraction-webpack-plugin": { - "version": "4.31.0", - "license": "GPL-2.0-or-later", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@wordpress/dependency-extraction-webpack-plugin/-/dependency-extraction-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-6r1Nsq/yoJSqx35iqXeqjID8GGrN7mISZXWCjbuYLIRRY1FxU+wbenj2BsdUtyUuAv8tAUH79cpgO0poYEDMoQ==", "dependencies": { - "json2php": "^0.0.7", - "webpack-sources": "^3.2.2" + "json2php": "^0.0.7" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "webpack": "^4.8.3 || ^5.0.0" + "webpack": "^5.0.0" } }, "node_modules/@wordpress/element": { "version": "4.20.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -6476,6 +6542,7 @@ }, "node_modules/@wordpress/element/node_modules/react": { "version": "17.0.2", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -6487,6 +6554,7 @@ }, "node_modules/@wordpress/element/node_modules/react-dom": { "version": "17.0.2", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -6499,6 +6567,7 @@ }, "node_modules/@wordpress/element/node_modules/scheduler": { "version": "0.20.2", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -6592,8 +6661,9 @@ } }, "node_modules/@wordpress/escape-html": { - "version": "2.48.0", - "license": "GPL-2.0-or-later", + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-2.53.0.tgz", + "integrity": "sha512-K2c6jg7qTGZIFj7uTCFR4FTK8PqHM4El7zdPAuK2apnZqhbdJEfH1/ogK+QZtn1VctyOXl0Mc+vzWoLUncey3g==", "dependencies": { "@babel/runtime": "^7.16.0" }, @@ -6921,12 +6991,49 @@ } }, "node_modules/@wordpress/icons": { - "version": "6.3.0", - "license": "GPL-2.0-or-later", + "version": "9.44.0", + "resolved": "https://registry.npmjs.org/@wordpress/icons/-/icons-9.44.0.tgz", + "integrity": "sha512-8VxsFkcUYGCk6qfrriSOxOFSDSgl4tNRnJo7019ABj8mTr4pqdJC7tYz88rOvtBbx9tswWXLBJM49vaBG8mOpw==", + "dependencies": { + "@babel/runtime": "^7.16.0", + "@wordpress/element": "^5.30.0", + "@wordpress/primitives": "^3.51.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@wordpress/icons/node_modules/@types/react": { + "version": "18.2.67", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.67.tgz", + "integrity": "sha512-vkIE2vTIMHQ/xL0rgmuoECBCkZFZeHr49HeWSc24AptMbNRo7pwSBvj73rlJJs9fGKj0koS+V7kQB1jHS0uCgw==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@wordpress/icons/node_modules/@types/react-dom": { + "version": "18.2.22", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz", + "integrity": "sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@wordpress/icons/node_modules/@wordpress/element": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@wordpress/element/-/element-5.30.0.tgz", + "integrity": "sha512-KH+KdZ1jzLRgA65Ez6Uy5dVbkS2az0uk1lDUpPRhApEY2J12SbsD/aVuznP/huO2Af+hyh4DDqbVS817Abcy2g==", "dependencies": { "@babel/runtime": "^7.16.0", - "@wordpress/element": "^4.1.1", - "@wordpress/primitives": "^3.1.1" + "@types/react": "^18.0.21", + "@types/react-dom": "^18.0.6", + "@wordpress/escape-html": "^2.53.0", + "change-case": "^4.1.2", + "is-plain-object": "^5.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "engines": { "node": ">=12" @@ -6944,11 +7051,12 @@ } }, "node_modules/@wordpress/primitives": { - "version": "3.46.0", - "license": "GPL-2.0-or-later", + "version": "3.51.0", + "resolved": "https://registry.npmjs.org/@wordpress/primitives/-/primitives-3.51.0.tgz", + "integrity": "sha512-UKz0h3BIU4hDMXnNlLZ6CZCe7eWuhDhzLj25+Ldfb71RuXMoqdH31ZN3gwIljVrLRWcBKVtgp9ULmuhdGvwzDA==", "dependencies": { "@babel/runtime": "^7.16.0", - "@wordpress/element": "^5.25.0", + "@wordpress/element": "^5.30.0", "classnames": "^2.3.1" }, "engines": { @@ -6956,8 +7064,9 @@ } }, "node_modules/@wordpress/primitives/node_modules/@types/react": { - "version": "18.2.46", - "license": "MIT", + "version": "18.2.67", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.67.tgz", + "integrity": "sha512-vkIE2vTIMHQ/xL0rgmuoECBCkZFZeHr49HeWSc24AptMbNRo7pwSBvj73rlJJs9fGKj0koS+V7kQB1jHS0uCgw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -6965,20 +7074,22 @@ } }, "node_modules/@wordpress/primitives/node_modules/@types/react-dom": { - "version": "18.2.18", - "license": "MIT", + "version": "18.2.22", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz", + "integrity": "sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==", "dependencies": { "@types/react": "*" } }, "node_modules/@wordpress/primitives/node_modules/@wordpress/element": { - "version": "5.25.0", - "license": "GPL-2.0-or-later", + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@wordpress/element/-/element-5.30.0.tgz", + "integrity": "sha512-KH+KdZ1jzLRgA65Ez6Uy5dVbkS2az0uk1lDUpPRhApEY2J12SbsD/aVuznP/huO2Af+hyh4DDqbVS817Abcy2g==", "dependencies": { "@babel/runtime": "^7.16.0", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", - "@wordpress/escape-html": "^2.48.0", + "@wordpress/escape-html": "^2.53.0", "change-case": "^4.1.2", "is-plain-object": "^5.0.0", "react": "^18.2.0", @@ -8627,7 +8738,8 @@ }, "node_modules/classnames": { "version": "2.5.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" }, "node_modules/clean-css": { "version": "5.3.3", @@ -14154,13 +14266,6 @@ "node": ">= 0.4" } }, - "node_modules/invariant": { - "version": "2.2.4", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/ipaddr.js": { "version": "2.1.0", "license": "MIT", @@ -17520,6 +17625,11 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, "node_modules/memory-fs": { "version": "0.4.1", "devOptional": true, @@ -20490,6 +20600,22 @@ "node": ">=0.10.0" } }, + "node_modules/react-window": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.10.tgz", + "integrity": "sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==", + "dependencies": { + "@babel/runtime": "^7.0.0", + "memoize-one": ">=3.1.1 <6" + }, + "engines": { + "node": ">8.0.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "license": "MIT", @@ -26688,7 +26814,7 @@ "@svgr/webpack": "^8.1.0", "@typescript-eslint/eslint-plugin": "^6.17.0", "@typescript-eslint/parser": "^6.17.0", - "@wordpress/dependency-extraction-webpack-plugin": "^4.31.0", + "@wordpress/dependency-extraction-webpack-plugin": "^5.4.0", "@wordpress/eslint-plugin": "^17.5.0", "@wordpress/jest-console": "^7.19.0", "babel-jest": "^29.7.0", @@ -28136,7 +28262,7 @@ "name": "tenup-theme", "version": "1.1.5-next.7", "dependencies": { - "@10up/block-components": "1.7.0", + "@10up/block-components": "^1.18.0", "@10up/component-accordion": "^2.1.5", "@linaria/core": "^5.0.2", "@linaria/react": "^5.0.3", diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/.gitignore b/packages/toolkit/__tests__/build-project-use-build-modules/.gitignore new file mode 100644 index 00000000..0fa2fd4f --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/.gitignore @@ -0,0 +1 @@ +./dist diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/css/admin-styles.css b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/css/admin-styles.css new file mode 100644 index 00000000..46b115dc --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/css/admin-styles.css @@ -0,0 +1 @@ +.admin-class { color: blue; } diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/css/frontend.css b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/css/frontend.css new file mode 100644 index 00000000..635ea838 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/css/frontend.css @@ -0,0 +1 @@ +.test { color: red; } diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/js/admin.js b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/js/admin.js new file mode 100644 index 00000000..015d49eb --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/js/admin.js @@ -0,0 +1,3 @@ +import '../css/admin-styles.css'; + +export const admin = () => {}; diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/js/frontend.js b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/js/frontend.js new file mode 100644 index 00000000..485b27e2 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/assets/js/frontend.js @@ -0,0 +1,14 @@ +/* eslint-disable*/ +import '../css/frontend.css'; +import * as React from 'react'; +import ReactDOM from 'react-dom'; +import { useState } from 'react'; + +const App = () => { + const [state] = useState(1); + + return

This is a react app {state}

; +}; + +ReactDOM.render(, document.getElementById('root')); + diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/block.json b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/block.json new file mode 100644 index 00000000..9e744b3e --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/block.json @@ -0,0 +1,45 @@ +{ + "title": "Example Block", + "description": "An Example Block", + "textdomain": "tenup-scaffold", + "name": "tenup/example", + "icon": "feedback", + "category": "tenup-scaffold-blocks", + "attributes": { + "title": { + "type": "string" + } + }, + "example": { + "attributes": { + "title": "Example Block" + } + }, + "supports": { + "align": false, + "alignWide": false, + "anchor": false, + "color": { + "gradients": false, + "background": false, + "text": false + }, + "customClassName": false, + "defaultStylePicker": false, + "typography": { + "fontSize": false, + "lineHeight": true + }, + "html": false, + "inserter": true, + "multiple": true, + "reusable": false, + "spacing": { + "padding": false + }, + "interactivity": true + }, + "editorScript": "file:./index.js", + "viewScriptModule": "file:./view-module.js", + "script": "file:./script.js" +} diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/edit.js b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/edit.js new file mode 100644 index 00000000..a44b8fc2 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/edit.js @@ -0,0 +1,4 @@ +// import './editor-styles.css'; + +const ExampleBlockEdit = () => {}; +export default ExampleBlockEdit; diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/editor-styles.css b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/editor-styles.css new file mode 100644 index 00000000..67cbeaf4 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/editor-styles.css @@ -0,0 +1 @@ +/* Editor specific styles */ diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/index.js b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/index.js new file mode 100644 index 00000000..900006bb --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/index.js @@ -0,0 +1,11 @@ +/* eslint-disable */ +import { registerBlockType } from '@wordpress/blocks'; + +import edit from './edit'; +import save from './save'; +import block from './block.json'; + +registerBlockType(block, { + edit, + save, +}); diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/save.js b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/save.js new file mode 100644 index 00000000..daa1ee54 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/save.js @@ -0,0 +1,8 @@ +/** + * See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#save + * + * @returns {null} Dynamic blocks do not save the HTML. + */ +const ExampleBlockSave = () => null; + +export default ExampleBlockSave; diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/view-module.js b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/view-module.js new file mode 100644 index 00000000..4072c697 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/__fixtures__/includes/blocks/example/view-module.js @@ -0,0 +1,14 @@ +// eslint-disable-next-line +import { store } from '@wordpress/interactivity'; + +store('example', { + actions: { + toggle: () => { + // eslint-disable-next-line no-console + console.log('Toggle Action'); + }, + }, +}); + +// eslint-disable-next-line no-console +console.log('View Module Loaded'); diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/package.json b/packages/toolkit/__tests__/build-project-use-build-modules/package.json new file mode 100644 index 00000000..0fc107b2 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/package.json @@ -0,0 +1,12 @@ +{ + "name": "test-build-project-modules", + "10up-toolkit": { + "entry": { + "admin": "./__fixtures__/assets/js/admin.js", + "frontend": "./__fixtures__/assets/js/frontend.js" + }, + "paths": { + "blocksDir": "./__fixtures__/includes/blocks" + } + } +} diff --git a/packages/toolkit/__tests__/build-project-use-build-modules/test.js b/packages/toolkit/__tests__/build-project-use-build-modules/test.js new file mode 100644 index 00000000..9acb938e --- /dev/null +++ b/packages/toolkit/__tests__/build-project-use-build-modules/test.js @@ -0,0 +1,61 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import spawn from 'cross-spawn'; +import fs from 'fs'; +import path from 'path'; + +describe('build a project (withb block-modules)', () => { + beforeAll(() => { + spawn.sync('node', ['../../scripts/build', '--block-modules'], { + cwd: __dirname, + }); + }); + + it('builds and compiles js and css', async () => { + expect(fs.existsSync(path.join(__dirname, 'dist', 'js', 'admin.js'))).toBeTruthy(); + expect(fs.existsSync(path.join(__dirname, 'dist', 'js', 'admin.asset.php'))).toBeTruthy(); + expect(fs.existsSync(path.join(__dirname, 'dist', 'js', 'frontend.js'))).toBeTruthy(); + expect( + fs.existsSync(path.join(__dirname, 'dist', 'js', 'frontend.asset.php')), + ).toBeTruthy(); + expect(fs.existsSync(path.join(__dirname, 'dist', 'css', 'frontend.css'))).toBeTruthy(); + }); + + it('adds react dependencies to .asset.php files', () => { + const frontendAssetPHP = fs + .readFileSync(path.join(__dirname, 'dist', 'js', 'frontend.asset.php')) + .toString(); + + expect(frontendAssetPHP).toMatch('wp-element'); + expect(frontendAssetPHP).toMatch('react-dom'); + expect(frontendAssetPHP).toMatch('react'); + + const viewModuleAsset = fs + .readFileSync( + path.join(__dirname, 'dist', 'blocks', 'example', 'view-module.asset.php'), + ) + .toString(); + + expect(viewModuleAsset).toMatch('@wordpress/interactivity'); + expect(viewModuleAsset).toMatch("'type' => 'module'"); + }); + + it('builds blocks with modules for vieewScriptModule', () => { + expect( + fs.existsSync(path.join(__dirname, 'dist', 'blocks', 'example', 'block.json')), + ).toBeTruthy(); + + expect( + fs.existsSync(path.join(__dirname, 'dist', 'blocks', 'example', 'index.js')), + ).toBeTruthy(); + + const viewModuleFile = path.join(__dirname, 'dist', 'blocks', 'example', 'view-module.js'); + + expect( + fs.existsSync(path.join(__dirname, 'dist', 'blocks', 'example', 'view-module.js')), + ).toBeTruthy(); + + const viewModuleFileContents = fs.readFileSync(viewModuleFile).toString(); + + expect(viewModuleFileContents).toMatch(/import \* as .* from "@wordpress\/interactivity";/); + }); +}); diff --git a/packages/toolkit/config/__tests__/__snapshots__/webpack-basic-config.js.snap b/packages/toolkit/config/__tests__/__snapshots__/webpack-basic-config.js.snap index a9a2eb0d..bcc392d7 100644 --- a/packages/toolkit/config/__tests__/__snapshots__/webpack-basic-config.js.snap +++ b/packages/toolkit/config/__tests__/__snapshots__/webpack-basic-config.js.snap @@ -4,7 +4,10 @@ exports[`webpack.config.js properly detects user config files in package mode 1` { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -311,7 +314,10 @@ exports[`webpack.config.js properly detects user config files in project mode 1` { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -624,7 +630,10 @@ exports[`webpack.config.js returns proper configs for package config 1`] = ` { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -930,7 +939,10 @@ exports[`webpack.config.js returns proper configs for package config with common { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -1236,7 +1248,10 @@ exports[`webpack.config.js returns proper configs for package config with peer d { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -1543,7 +1558,10 @@ exports[`webpack.config.js returns proper configs for project configs 1`] = ` { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, diff --git a/packages/toolkit/config/__tests__/__snapshots__/webpack-cli-arguments.js.snap b/packages/toolkit/config/__tests__/__snapshots__/webpack-cli-arguments.js.snap index 7aca43fd..b1260312 100644 --- a/packages/toolkit/config/__tests__/__snapshots__/webpack-cli-arguments.js.snap +++ b/packages/toolkit/config/__tests__/__snapshots__/webpack-cli-arguments.js.snap @@ -7,7 +7,10 @@ exports[`webpack.config.js adds devServer config when passing the --dev-server f "port": 3000, }, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -314,7 +317,10 @@ exports[`webpack.config.js allows changing browsersync port 1`] = ` { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -624,11 +630,640 @@ exports[`webpack.config.js allows changing browsersync port 1`] = ` } `; +exports[`webpack.config.js builds modules 1`] = ` +[ + { + "devServer": undefined, + "devtool": false, + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", + "experiments": { + "outputModule": false, + }, + "externals": { + "jquery": "jQuery", + "lodash": "lodash", + }, + "mode": "production", + "module": { + "rules": [ + { + "exclude": "input => shouldExclude(input, include)", + "test": /\\^\\(\\?!\\.\\*\\\\\\.d\\\\\\.tsx\\?\\$\\)\\.\\*\\\\\\.\\[tj\\]sx\\?\\$/, + "use": [ + { + "loader": "/config/webpack/plugins/noop-loader.js", + }, + { + "loader": "/node_modules/babel-loader/lib/index.js", + "options": { + "babelrc": false, + "cacheDirectory": true, + "configFile": false, + "plugins": [], + "presets": [ + [ + "/packages/babel-preset-default/index.js", + { + "targets": [ + "> 1%", + "Firefox ESR", + "last 2 versions", + "not ie <= 11", + "not ie_mob <=11", + ], + "useBuiltIns": "usage", + "wordpress": true, + }, + ], + [ + "@linaria", + { + "babelOptions": { + "babelrc": false, + "configFile": false, + "presets": [ + [ + "/packages/babel-preset-default/index.js", + { + "targets": [ + "> 1%", + "Firefox ESR", + "last 2 versions", + "not ie <= 11", + "not ie_mob <=11", + ], + "useBuiltIns": "usage", + "wordpress": true, + }, + ], + ], + "sourceType": "unambiguous", + }, + }, + ], + ], + "sourceType": "unambiguous", + }, + }, + { + "loader": "@linaria/webpack-loader", + "options": { + "babelOptions": { + "babelrc": false, + "configFile": false, + "plugins": [], + "presets": [ + [ + "/packages/babel-preset-default/index.js", + { + "targets": [ + "> 1%", + "Firefox ESR", + "last 2 versions", + "not ie <= 11", + "not ie_mob <=11", + ], + "useBuiltIns": "usage", + "wordpress": true, + }, + ], + [ + "@linaria", + { + "babelOptions": { + "babelrc": false, + "configFile": false, + "presets": [ + [ + "/packages/babel-preset-default/index.js", + { + "targets": [ + "> 1%", + "Firefox ESR", + "last 2 versions", + "not ie <= 11", + "not ie_mob <=11", + ], + "useBuiltIns": "usage", + "wordpress": true, + }, + ], + ], + "sourceType": "unambiguous", + }, + }, + ], + ], + "sourceType": "unambiguous", + }, + "extension": ".linaria.module.css", + "overrideContext": "context => ({ + ...context, + $RefreshReg$: () => {} + })", + "sourceMap": false, + }, + }, + ], + }, + { + "test": /\\\\\\.svg\\$/, + "use": [ + "@svgr/webpack", + "url-loader", + ], + }, + { + "exclude": [ + /\\\\\\.module\\\\\\.css\\$/, + /\\\\\\.linaria\\\\\\.module\\\\\\.css/, + ], + "test": /\\\\\\.css\\$/, + "use": [ + { + "loader": "/node_modules/mini-css-extract-plugin/dist/loader.js", + }, + { + "loader": "/node_modules/css-loader/dist/cjs.js", + "options": { + "sourceMap": false, + "url": false, + }, + }, + { + "loader": "/node_modules/postcss-loader/dist/cjs.js", + "options": { + "postcssOptions": { + "config": "/config/postcss.config.js", + }, + }, + }, + ], + }, + { + "exclude": [ + /\\\\\\.module\\\\\\.css\\$/, + /\\\\\\.linaria\\\\\\.module\\\\\\.css/, + ], + "test": /\\\\\\.\\(sc\\|sa\\)ss\\$/, + "use": [ + { + "loader": "/node_modules/mini-css-extract-plugin/dist/loader.js", + }, + { + "loader": "/node_modules/css-loader/dist/cjs.js", + "options": { + "sourceMap": false, + "url": false, + }, + }, + { + "loader": "/node_modules/postcss-loader/dist/cjs.js", + "options": { + "postcssOptions": { + "config": "/config/postcss.config.js", + }, + }, + }, + { + "loader": "/node_modules/sass-loader/dist/cjs.js", + "options": { + "sourceMap": false, + }, + }, + ], + }, + { + "exclude": [ + /\\\\\\.linaria\\\\\\.module\\\\\\.css\\$/, + ], + "test": /\\\\\\.module\\\\\\.css\\$/, + "use": [ + { + "loader": "/node_modules/mini-css-extract-plugin/dist/loader.js", + }, + { + "loader": "/node_modules/css-loader/dist/cjs.js", + "options": { + "import": false, + "modules": true, + "sourceMap": false, + "url": false, + }, + }, + { + "loader": "/node_modules/postcss-loader/dist/cjs.js", + "options": { + "postcssOptions": { + "config": "/config/postcss.config.js", + }, + }, + }, + { + "loader": "/node_modules/sass-loader/dist/cjs.js", + "options": { + "sourceMap": false, + }, + }, + ], + }, + { + "test": /\\\\\\.linaria\\\\\\.module\\\\\\.css/, + "use": [ + { + "loader": "/node_modules/mini-css-extract-plugin/dist/loader.js", + }, + { + "loader": "css-loader", + }, + ], + }, + ], + }, + "optimization": { + "concatenateModules": true, + "minimizer": [ + "TerserPlugin: {"test":{},"extractComments":true,"parallel":true,"minimizer":{"options":{"parse":{"ecma":8},"compress":{"ecma":5,"warnings":false,"comparisons":false,"inline":2}}}}", + "ImageMinimizerPlugin: {"minimizer":{},"loader":true,"test":{},"deleteOriginalAssets":true}", + "ImageMinimizerPlugin: {"minimizer":{},"loader":true,"test":{},"deleteOriginalAssets":true}", + ], + "runtimeChunk": false, + }, + "output": { + "chunkFilename": "js/[name].[contenthash].chunk.js", + "clean": false, + "filename": "pathData => { + if (pathData.chunk.name === 'runtime') { + return 'fast-refresh/hmr-runtime.js'; + } + // match windows and posix paths + const isBlockAsset = buildFiles[pathData.chunk.name].match(/\\/blocks?\\//) || buildFiles[pathData.chunk.name].match(/\\\\blocks?\\\\/); + return isBlockAsset ? filenames.block : filenames.js; + }", + "path": "/dist", + "publicPath": undefined, + }, + "performance": { + "hints": "warning", + "maxAssetSize": 102400, + "maxEntrypointSize": 409600, + }, + "plugins": [ + "ESLintWebpackPlugin: {"cache":true,"cacheLocation":"node_modules/.cache/eslint-webpack-plugin/.eslintcache","extensions":"js","emitError":true,"emitWarning":true,"failOnError":false,"resourceQueryExclude":[],"fix":false,"lintDirtyModulesOnly":true}", + "MiniCssExtractPlugin: {"ignoreOrder":false,"runtime":true,"chunkFilename":"[id].css"}", + "CopyPlugin: {}", + "StylelintWebpackPlugin: {"cache":true,"cacheLocation":"node_modules/.cache/stylelint-webpack-plugin/.stylelintcache","extensions":["css","scss","sass"],"emitError":true,"emitWarning":true,"failOnError":false,"context":"/assets2","files":"**/*.(s(c|a)ss|css)","allowEmptyInput":true,"lintDirtyModulesOnly":true,"configFile":"/config/stylelint.config.js"}", + "WebpackBarPlugin: {"name":"webpack","color":"green","reporters":["basic"],"reporter":null}", + "DependencyExtractionWebpackPlugin: {"combineAssets":false,"combinedOutputFile":null,"externalizedReport":false,"injectPolyfill":false,"outputFormat":"php","outputFilename":null,"useDefaults":true}", + "CleanExtractedDeps: {}", + "WebpackRemoveEmptyScriptsPlugin: {"enabled":true,"verbose":false,"extensions":{},"ignore":[],"remove":{}}", + "TenUpToolkitTscPlugin: {}", + ], + "resolve": { + "alias": { + "lodash-es": "lodash", + }, + "extensions": [ + ".tsx", + ".ts", + ".js", + ], + }, + "stats": { + "all": false, + "assets": true, + "errorDetails": true, + "errors": true, + "excludeAssets": /\\\\\\.\\(jpe\\?g\\|png\\|gif\\|svg\\|woff\\|woff2\\)\\$/i, + "moduleTrace": true, + "modules": true, + "performance": true, + "warnings": true, + }, + "target": "browserslist:> 1%, Firefox ESR, last 2 versions, not ie <= 11, not ie_mob <=11", + }, + { + "devServer": undefined, + "devtool": false, + "entry": "() => getEntryPoints({ + ...config, + buildType: 'module' + })", + "experiments": { + "outputModule": true, + }, + "externals": { + "jquery": "jQuery", + "lodash": "lodash", + }, + "mode": "production", + "module": { + "rules": [ + { + "exclude": "input => shouldExclude(input, include)", + "test": /\\^\\(\\?!\\.\\*\\\\\\.d\\\\\\.tsx\\?\\$\\)\\.\\*\\\\\\.\\[tj\\]sx\\?\\$/, + "use": [ + { + "loader": "/config/webpack/plugins/noop-loader.js", + }, + { + "loader": "/node_modules/babel-loader/lib/index.js", + "options": { + "babelrc": false, + "cacheDirectory": true, + "configFile": false, + "plugins": [], + "presets": [ + [ + "/packages/babel-preset-default/index.js", + { + "targets": [ + "> 1%", + "Firefox ESR", + "last 2 versions", + "not ie <= 11", + "not ie_mob <=11", + ], + "useBuiltIns": "usage", + "wordpress": true, + }, + ], + [ + "@linaria", + { + "babelOptions": { + "babelrc": false, + "configFile": false, + "presets": [ + [ + "/packages/babel-preset-default/index.js", + { + "targets": [ + "> 1%", + "Firefox ESR", + "last 2 versions", + "not ie <= 11", + "not ie_mob <=11", + ], + "useBuiltIns": "usage", + "wordpress": true, + }, + ], + ], + "sourceType": "unambiguous", + }, + }, + ], + ], + "sourceType": "unambiguous", + }, + }, + { + "loader": "@linaria/webpack-loader", + "options": { + "babelOptions": { + "babelrc": false, + "configFile": false, + "plugins": [], + "presets": [ + [ + "/packages/babel-preset-default/index.js", + { + "targets": [ + "> 1%", + "Firefox ESR", + "last 2 versions", + "not ie <= 11", + "not ie_mob <=11", + ], + "useBuiltIns": "usage", + "wordpress": true, + }, + ], + [ + "@linaria", + { + "babelOptions": { + "babelrc": false, + "configFile": false, + "presets": [ + [ + "/packages/babel-preset-default/index.js", + { + "targets": [ + "> 1%", + "Firefox ESR", + "last 2 versions", + "not ie <= 11", + "not ie_mob <=11", + ], + "useBuiltIns": "usage", + "wordpress": true, + }, + ], + ], + "sourceType": "unambiguous", + }, + }, + ], + ], + "sourceType": "unambiguous", + }, + "extension": ".linaria.module.css", + "overrideContext": "context => ({ + ...context, + $RefreshReg$: () => {} + })", + "sourceMap": false, + }, + }, + ], + }, + { + "test": /\\\\\\.svg\\$/, + "use": [ + "@svgr/webpack", + "url-loader", + ], + }, + { + "exclude": [ + /\\\\\\.module\\\\\\.css\\$/, + /\\\\\\.linaria\\\\\\.module\\\\\\.css/, + ], + "test": /\\\\\\.css\\$/, + "use": [ + { + "loader": "/node_modules/mini-css-extract-plugin/dist/loader.js", + }, + { + "loader": "/node_modules/css-loader/dist/cjs.js", + "options": { + "sourceMap": false, + "url": false, + }, + }, + { + "loader": "/node_modules/postcss-loader/dist/cjs.js", + "options": { + "postcssOptions": { + "config": "/config/postcss.config.js", + }, + }, + }, + ], + }, + { + "exclude": [ + /\\\\\\.module\\\\\\.css\\$/, + /\\\\\\.linaria\\\\\\.module\\\\\\.css/, + ], + "test": /\\\\\\.\\(sc\\|sa\\)ss\\$/, + "use": [ + { + "loader": "/node_modules/mini-css-extract-plugin/dist/loader.js", + }, + { + "loader": "/node_modules/css-loader/dist/cjs.js", + "options": { + "sourceMap": false, + "url": false, + }, + }, + { + "loader": "/node_modules/postcss-loader/dist/cjs.js", + "options": { + "postcssOptions": { + "config": "/config/postcss.config.js", + }, + }, + }, + { + "loader": "/node_modules/sass-loader/dist/cjs.js", + "options": { + "sourceMap": false, + }, + }, + ], + }, + { + "exclude": [ + /\\\\\\.linaria\\\\\\.module\\\\\\.css\\$/, + ], + "test": /\\\\\\.module\\\\\\.css\\$/, + "use": [ + { + "loader": "/node_modules/mini-css-extract-plugin/dist/loader.js", + }, + { + "loader": "/node_modules/css-loader/dist/cjs.js", + "options": { + "import": false, + "modules": true, + "sourceMap": false, + "url": false, + }, + }, + { + "loader": "/node_modules/postcss-loader/dist/cjs.js", + "options": { + "postcssOptions": { + "config": "/config/postcss.config.js", + }, + }, + }, + { + "loader": "/node_modules/sass-loader/dist/cjs.js", + "options": { + "sourceMap": false, + }, + }, + ], + }, + { + "test": /\\\\\\.linaria\\\\\\.module\\\\\\.css/, + "use": [ + { + "loader": "/node_modules/mini-css-extract-plugin/dist/loader.js", + }, + { + "loader": "css-loader", + }, + ], + }, + ], + }, + "optimization": { + "concatenateModules": true, + "minimizer": [ + "TerserPlugin: {"test":{},"extractComments":true,"parallel":true,"minimizer":{"options":{"parse":{"ecma":8},"compress":{"ecma":5,"warnings":false,"comparisons":false,"inline":2}}}}", + "ImageMinimizerPlugin: {"minimizer":{},"loader":true,"test":{},"deleteOriginalAssets":true}", + "ImageMinimizerPlugin: {"minimizer":{},"loader":true,"test":{},"deleteOriginalAssets":true}", + ], + "runtimeChunk": false, + }, + "output": { + "chunkFormat": "module", + "clean": false, + "filename": "blocks/[name].js", + "library": { + "type": "module", + }, + "module": true, + }, + "performance": { + "hints": "warning", + "maxAssetSize": 102400, + "maxEntrypointSize": 409600, + }, + "plugins": [ + "ESLintWebpackPlugin: {"cache":true,"cacheLocation":"node_modules/.cache/eslint-webpack-plugin/.eslintcache","extensions":"js","emitError":true,"emitWarning":true,"failOnError":false,"resourceQueryExclude":[],"fix":false,"lintDirtyModulesOnly":true}", + "MiniCssExtractPlugin: {"ignoreOrder":false,"runtime":true,"chunkFilename":"[id].css"}", + "CopyPlugin: {}", + "StylelintWebpackPlugin: {"cache":true,"cacheLocation":"node_modules/.cache/stylelint-webpack-plugin/.stylelintcache","extensions":["css","scss","sass"],"emitError":true,"emitWarning":true,"failOnError":false,"context":"/assets2","files":"**/*.(s(c|a)ss|css)","allowEmptyInput":true,"lintDirtyModulesOnly":true,"configFile":"/config/stylelint.config.js"}", + "WebpackBarPlugin: {"name":"webpack","color":"green","reporters":["basic"],"reporter":null}", + "DependencyExtractionWebpackPlugin: {"combineAssets":false,"combinedOutputFile":null,"externalizedReport":false,"injectPolyfill":false,"outputFormat":"php","outputFilename":null,"useDefaults":true}", + "CleanExtractedDeps: {}", + "WebpackRemoveEmptyScriptsPlugin: {"enabled":true,"verbose":false,"extensions":{},"ignore":[],"remove":{}}", + "TenUpToolkitTscPlugin: {}", + ], + "resolve": { + "alias": { + "lodash-es": "lodash", + }, + "extensions": [ + ".tsx", + ".ts", + ".js", + ], + }, + "stats": { + "all": false, + "assets": true, + "errorDetails": true, + "errors": true, + "excludeAssets": /\\\\\\.\\(jpe\\?g\\|png\\|gif\\|svg\\|woff\\|woff2\\)\\$/i, + "moduleTrace": true, + "modules": true, + "performance": true, + "warnings": true, + }, + "target": "es2020", + }, +] +`; + exports[`webpack.config.js includes webpack-bundle-analyzer when using --analyze 1`] = ` { "devServer": undefined, "devtool": false, - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -942,7 +1577,10 @@ exports[`webpack.config.js includes webpack-bundle-analyzer when using --analyze { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -1255,7 +1893,10 @@ exports[`webpack.config.js returns proper configs for package config with common { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, @@ -1561,7 +2202,10 @@ exports[`webpack.config.js takes the --target option into account 1`] = ` { "devServer": undefined, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, diff --git a/packages/toolkit/config/__tests__/__snapshots__/webpack-fast-refresh.js.snap b/packages/toolkit/config/__tests__/__snapshots__/webpack-fast-refresh.js.snap index 67df7e90..97eb47f3 100644 --- a/packages/toolkit/config/__tests__/__snapshots__/webpack-fast-refresh.js.snap +++ b/packages/toolkit/config/__tests__/__snapshots__/webpack-fast-refresh.js.snap @@ -27,7 +27,10 @@ exports[`webpack.config.js includes react-webpack-fast-refresh with the --hot op }, }, "devtool": "source-map", - "entry": "() => getEntryPoints(config)", + "entry": "() => getEntryPoints({ + ...config, + buildType: 'script' + })", "experiments": { "outputModule": false, }, diff --git a/packages/toolkit/config/__tests__/webpack-cli-arguments.js b/packages/toolkit/config/__tests__/webpack-cli-arguments.js index a47c7652..26dc7296 100644 --- a/packages/toolkit/config/__tests__/webpack-cli-arguments.js +++ b/packages/toolkit/config/__tests__/webpack-cli-arguments.js @@ -187,9 +187,40 @@ describe('webpack.config.js', () => { // eslint-disable-next-line global-require webpackConfig = require('../webpack.config'); }); - expect(webpackConfig.devtool).toBe('source-map'); process.argv.pop(); process.env.NODE_ENV = originalNodeEnv; }); + + it('builds modules', () => { + const originalNodeEnv = process.env.NODE_ENV; + process.env.NODE_ENV = 'production'; + process.argv.push('--block-modules'); + const entryBuildFiles = { + entry1: 'entry1.js', + entry2: 'entry2.js', + entry3: 'entry3.js', + }; + getBuildFilesMock.mockReturnValue(entryBuildFiles); + getPackageMock.mockReturnValue({ + '10up-toolkit': { + entry: entryBuildFiles, + paths: { + blocksDir: './includes2/blocks/', + srcDir: './assets2/', + cssLoaderPaths: ['./assets2/css', './includes2/blocks'], + copyAssetsDir: './assets2/', + }, + }, + }); + let webpackConfig; + jest.isolateModules(() => { + // eslint-disable-next-line global-require + webpackConfig = require('../webpack.config'); + }); + + expect(webpackConfig).toMatchSnapshot(); + process.argv.pop(); + process.env.NODE_ENV = originalNodeEnv; + }); }); diff --git a/packages/toolkit/config/webpack.config.js b/packages/toolkit/config/webpack.config.js index 17251ce8..7137a2e5 100644 --- a/packages/toolkit/config/webpack.config.js +++ b/packages/toolkit/config/webpack.config.js @@ -30,6 +30,7 @@ const buildFiles = getBuildFiles(); const isPackage = typeof source !== 'undefined' && typeof main !== 'undefined'; const isProduction = process.env.NODE_ENV === 'production'; const mode = isProduction ? 'production' : 'development'; +const useBlockModules = projectConfig.useBlockModules || false; const defaultTargets = [ '> 1%', @@ -49,13 +50,10 @@ const config = { defaultTargets, }; -module.exports = { +const baseConfig = { devtool: !isProduction || projectConfig.sourcemap ? 'source-map' : false, mode, devServer: getDevServer(config), - // using a function here in order to re-evaluate - // the entrypoints whenever something changes - entry: () => getEntryPoints(config), output: getOutput(config), target: getTarget(config), resolve: getResolve(config), @@ -69,3 +67,36 @@ module.exports = { outputModule: packageConfig.packageType === 'module', }, }; + +const scriptsConfig = { + ...baseConfig, + entry: () => getEntryPoints({ ...config, buildType: 'script' }), +}; + +const moduleConfig = { + ...baseConfig, + + entry: () => getEntryPoints({ ...config, buildType: 'module' }), + plugins: getPlugins({ ...config, isModule: true }), + devServer: getDevServer({ ...config, isModule: true }), + module: getModules({ ...config, isModule: true }), + target: getTarget({ ...config, isModule: true }), + + experiments: { + ...baseConfig.experiments, + outputModule: true, + }, + + output: { + clean: false, + module: true, + chunkFormat: 'module', + library: { + ...baseConfig.output.library, + type: 'module', + }, + filename: 'blocks/[name].js', + }, +}; + +module.exports = useBlockModules ? [scriptsConfig, moduleConfig] : scriptsConfig; diff --git a/packages/toolkit/config/webpack/__tests__/output.js b/packages/toolkit/config/webpack/__tests__/output.js index 53b5c34a..9e3ce1af 100644 --- a/packages/toolkit/config/webpack/__tests__/output.js +++ b/packages/toolkit/config/webpack/__tests__/output.js @@ -25,6 +25,7 @@ describe('output module function', () => { it('return project output config when isPackage is false', () => { expect( output({ + isProduction: true, isPackage: false, packageConfig: {}, projectConfig: { hot: false, filenames: { jsChunk: 'js/[name].js' } }, @@ -37,6 +38,7 @@ describe('output module function', () => { expect( output({ + isProduction: false, isPackage: false, packageConfig: {}, projectConfig: { hot: true, filenames: { jsChunk: 'js/[name].js' } }, diff --git a/packages/toolkit/config/webpack/devServer.js b/packages/toolkit/config/webpack/devServer.js index 6c20bded..4dd6365e 100644 --- a/packages/toolkit/config/webpack/devServer.js +++ b/packages/toolkit/config/webpack/devServer.js @@ -1,16 +1,20 @@ -module.exports = ({ isPackage, projectConfig: { devServer, devURL, hot, devServerPort } }) => { +module.exports = ({ + isPackage, + isModule, + projectConfig: { devServer, devURL, hot, devServerPort }, +}) => { if (!devServer && !hot) { return undefined; } - if (isPackage && devServer) { + if ((isPackage && devServer) || (isModule && devServer)) { return { compress: true, port: Number(devServerPort), }; } - if (!isPackage && hot) { + if ((!isPackage && hot) || (!isModule && hot)) { const allowedHosts = ['.test', '.local']; try { diff --git a/packages/toolkit/config/webpack/entry.js b/packages/toolkit/config/webpack/entry.js index f94877f9..5f66b3af 100644 --- a/packages/toolkit/config/webpack/entry.js +++ b/packages/toolkit/config/webpack/entry.js @@ -7,6 +7,7 @@ const removeDistFolder = (file) => { }; module.exports = ({ + buildType = 'script', isPackage, projectConfig: { devServer, paths, useBlockAssets, filenames }, packageConfig: { packageType, source, main, umd, libraryName }, @@ -36,12 +37,31 @@ module.exports = ({ // at which point they are completely empty and therefore not valid JSON try { // get all assets from the block.json file - const { editorScript, script, viewScript, style, editorStyle } = JSON.parse( - readFileSync(blockMetadataFile), - ); + const { + editorScript, + script, + viewScript, + scriptModule, + viewScriptModule, + style, + editorStyle, + viewStyle, + } = JSON.parse(readFileSync(blockMetadataFile)); + + const assets = []; + + if (buildType === 'script') { + assets.push( + ...[editorScript, script, viewScript, style, editorStyle, viewStyle].filter( + Boolean, + ), + ); + } else if (buildType === 'module') { + assets.push(...[scriptModule, viewScriptModule].filter(Boolean)); + } // generate a new entrypoint for each of the assets - [editorScript, script, viewScript, style, editorStyle] + assets .flat() .filter((rawFilepath) => rawFilepath && rawFilepath.startsWith('file:')) // assets can be files or handles. we only want files .forEach((rawFilepath) => { @@ -84,6 +104,10 @@ module.exports = ({ }, {}); } + if (buildType === 'module') { + return additionalEntrypoints; + } + // merge the new entrypoints with the existing ones Object.assign(buildFiles, additionalEntrypoints); diff --git a/packages/toolkit/config/webpack/modules.js b/packages/toolkit/config/webpack/modules.js index 0846befc..8a4ad91c 100644 --- a/packages/toolkit/config/webpack/modules.js +++ b/packages/toolkit/config/webpack/modules.js @@ -59,10 +59,11 @@ const LINARIA_EXTENSION_REGEXP = /\.linaria\.module\.css/; module.exports = ({ isProduction, isPackage, + isModule, defaultTargets, projectConfig: { wordpress, hot, include }, }) => { - const hasReactFastRefresh = hot && !isProduction; + const hasReactFastRefresh = hot && !isProduction && !isModule; // Provide a default configuration if there's not // one explicitly available in the project. diff --git a/packages/toolkit/config/webpack/output.js b/packages/toolkit/config/webpack/output.js index e0e86ae4..74fbf2e1 100644 --- a/packages/toolkit/config/webpack/output.js +++ b/packages/toolkit/config/webpack/output.js @@ -3,7 +3,7 @@ const path = require('path'); module.exports = ({ isPackage, packageConfig: { packageType, main }, - projectConfig: { filenames, hot, publicPath }, + projectConfig: { filenames, useBlockModules, hot, publicPath }, buildFiles, }) => { if (isPackage) { @@ -22,8 +22,8 @@ module.exports = ({ } return { - // when in hot reload mode we should not clear dist folder between builds - clean: !hot, + // when in block module mode or when hot reloading is active we should not clear dist folder between builds + clean: !useBlockModules && !hot, path: path.resolve(process.cwd(), 'dist'), chunkFilename: filenames.jsChunk, publicPath, diff --git a/packages/toolkit/config/webpack/plugins.js b/packages/toolkit/config/webpack/plugins.js index edc87ab5..1d00c6ee 100644 --- a/packages/toolkit/config/webpack/plugins.js +++ b/packages/toolkit/config/webpack/plugins.js @@ -34,6 +34,7 @@ const webpackbarArguments = module.exports = ({ isPackage, + isModule = false, isProduction, projectConfig: { devServer, @@ -49,7 +50,7 @@ module.exports = ({ packageConfig: { style }, buildFiles, }) => { - const hasReactFastRefresh = hot && !isProduction; + const hasReactFastRefresh = hot && !isProduction && !isModule; const hasBrowserSync = isPackageInstalled('browser-sync-webpack-plugin') && isPackageInstalled('browser-sync'); @@ -202,6 +203,10 @@ module.exports = ({ injectPolyfill: false, requestToHandle: (request) => { if (request.includes('react-refresh/runtime')) { + if (isModule) { + return undefined; + } + return 'tenup-toolkit-react-refresh-runtime'; } diff --git a/packages/toolkit/config/webpack/target.js b/packages/toolkit/config/webpack/target.js index 32277225..297eeee4 100644 --- a/packages/toolkit/config/webpack/target.js +++ b/packages/toolkit/config/webpack/target.js @@ -1,9 +1,9 @@ -module.exports = ({ defaultTargets, packageConfig: { target, packageType } }) => { +module.exports = ({ defaultTargets, isModule, packageConfig: { target, packageType } }) => { if (target) { return target; } - if (packageType === 'module') { + if (packageType === 'module' || isModule) { return 'es2020'; } diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index 1c999b37..43ae3225 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -23,7 +23,7 @@ "@svgr/webpack": "^8.1.0", "@typescript-eslint/eslint-plugin": "^6.17.0", "@typescript-eslint/parser": "^6.17.0", - "@wordpress/dependency-extraction-webpack-plugin": "^4.31.0", + "@wordpress/dependency-extraction-webpack-plugin": "^5.4.0", "@wordpress/jest-console": "^7.19.0", "@wordpress/eslint-plugin": "^17.5.0", "babel-jest": "^29.7.0", diff --git a/packages/toolkit/utils/config.js b/packages/toolkit/utils/config.js index 5b2ec5c6..ca8554ad 100644 --- a/packages/toolkit/utils/config.js +++ b/packages/toolkit/utils/config.js @@ -109,6 +109,7 @@ const getDefaultConfig = () => { const analyze = hasArgInCLI('--analyze'); const include = hasArgInCLI('--include') ? getArgFromCLI('--include').split(',') : []; const sourcemap = hasArgInCLI('--sourcemap'); + const useBlockModules = hasArgInCLI('--block-modules') || false; const buildFilesPath = hasProjectFile('buildfiles.config.js') ? fromProjectRoot('buildfiles.config.js') @@ -138,6 +139,7 @@ const getDefaultConfig = () => { !process.env.TENUP_NO_EXTERNALS, publicPath: process.env.ASSET_PATH || undefined, useBlockAssets: true, + useBlockModules, include, }; }; diff --git a/projects/10up-theme/includes/blocks/example/block.json b/projects/10up-theme/includes/blocks/example/block.json index a8bd8bca..15e0b060 100644 --- a/projects/10up-theme/includes/blocks/example/block.json +++ b/projects/10up-theme/includes/blocks/example/block.json @@ -36,11 +36,13 @@ "reusable": false, "spacing": { "padding": false - } + }, + "interactivity": true }, "editorScript": "file:./index.js", "editorStyle": "file:./editor.css", "style": "file:./style.css", "viewScript": "file:./view.js", + "viewScriptModule": "file:./view-module.js", "script": "file:./script.js" } diff --git a/projects/10up-theme/includes/blocks/example/markup.php b/projects/10up-theme/includes/blocks/example/markup.php index 62760819..978578f0 100644 --- a/projects/10up-theme/includes/blocks/example/markup.php +++ b/projects/10up-theme/includes/blocks/example/markup.php @@ -11,8 +11,9 @@ */ ?> -
> +
'example']); // phpcs:ignore ?>>

+
diff --git a/projects/10up-theme/includes/blocks/example/script.js b/projects/10up-theme/includes/blocks/example/script.js index 0e4cea6f..3154acf9 100644 --- a/projects/10up-theme/includes/blocks/example/script.js +++ b/projects/10up-theme/includes/blocks/example/script.js @@ -2,5 +2,5 @@ import domReady from '@wordpress/dom-ready'; domReady(() => { // eslint-disable-next-line no-console - console.log('DOM ready!'); + console.log('Script loaded!'); }); diff --git a/projects/10up-theme/includes/blocks/example/view-module.js b/projects/10up-theme/includes/blocks/example/view-module.js new file mode 100644 index 00000000..987f6e8c --- /dev/null +++ b/projects/10up-theme/includes/blocks/example/view-module.js @@ -0,0 +1,13 @@ +import { store } from '@wordpress/interactivity'; + +store('example', { + actions: { + toggle: () => { + // eslint-disable-next-line no-console + console.log('Toggle Action'); + }, + }, +}); + +// eslint-disable-next-line no-console +console.log('View Module Loaded'); diff --git a/projects/10up-theme/includes/blocks/example/view.js b/projects/10up-theme/includes/blocks/example/view.js index 0e4cea6f..09ac6988 100644 --- a/projects/10up-theme/includes/blocks/example/view.js +++ b/projects/10up-theme/includes/blocks/example/view.js @@ -2,5 +2,5 @@ import domReady from '@wordpress/dom-ready'; domReady(() => { // eslint-disable-next-line no-console - console.log('DOM ready!'); + console.log('View Script Loaded'); }); diff --git a/projects/10up-theme/package.json b/projects/10up-theme/package.json index a79c1821..9d4f0fe6 100644 --- a/projects/10up-theme/package.json +++ b/projects/10up-theme/package.json @@ -3,9 +3,9 @@ "version": "1.1.5-next.7", "private": true, "scripts": { - "start": "10up-toolkit start --port=3002 --hot --include=@10up/block-components", - "watch": "10up-toolkit start --include=@10up/block-components", - "build": "10up-toolkit build --include=@10up/block-components", + "start": "10up-toolkit start", + "watch": "10up-toolkit start", + "build": "10up-toolkit build", "format-js": "10up-toolkit format-js", "lint": "npm run lint-js && npm run lint-style", "lint-js": "10up-toolkit lint-js", @@ -23,7 +23,7 @@ "10up-toolkit": "^6.0.0" }, "dependencies": { - "@10up/block-components": "1.7.0", + "@10up/block-components": "^1.18.0", "@10up/component-accordion": "^2.1.5", "@linaria/core": "^5.0.2", "@linaria/react": "^5.0.3", @@ -33,11 +33,10 @@ "react-dom": "^18.2.0" }, "10up-toolkit": { - "devURL": "https://my-project.test", "useBlockAssets": true, + "useBlockModules": true, "entry": { "admin": "./assets/js/admin/admin.js", - "blocks": "./includes/blocks/blocks.js", "frontend": "./assets/js/frontend/frontend.js", "shared": "./assets/js/shared/shared.js", "styleguide": "./assets/js/styleguide/styleguide.js",