From f5942faf2500875f62af1a672bfedb790df62332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcholas=20Andr=C3=A9?= Date: Mon, 13 Nov 2023 11:24:26 -0300 Subject: [PATCH 1/3] chore: update package-lock --- package-lock.json | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7a225e581..ef0f8436b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,13 +13,7 @@ "wp/*" ], "dependencies": { - "express": "^4.18.1", - "turbo-darwin-64": "1.9.3", - "turbo-darwin-arm64": "1.9.3", - "turbo-linux-64": "1.9.3", - "turbo-linux-arm64": "1.9.3", - "turbo-windows-64": "1.9.3", - "turbo-windows-arm64": "1.9.3" + "express": "^4.18.1" }, "devDependencies": { "@10up/eslint-config": "^3.1.0", @@ -21758,7 +21752,7 @@ }, "packages/next": { "name": "@headstartwp/next", - "version": "1.1.4", + "version": "1.1.5", "license": "MIT", "dependencies": { "@headstartwp/core": "^1.1.2", @@ -21924,7 +21918,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@headstartwp/core": "^1.1.2", - "@headstartwp/next": "^1.1.4", + "@headstartwp/next": "^1.1.5", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", @@ -21953,7 +21947,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@headstartwp/core": "^1.1.2", - "@headstartwp/next": "^1.1.4", + "@headstartwp/next": "^1.1.5", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", @@ -21983,7 +21977,7 @@ "dependencies": { "@10up/next-redis-cache-provider": "^0.1.5", "@headstartwp/core": "^1.1.2", - "@headstartwp/next": "^1.1.4", + "@headstartwp/next": "^1.1.5", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", @@ -22012,7 +22006,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@headstartwp/core": "^1.1.2", - "@headstartwp/next": "^1.1.4", + "@headstartwp/next": "^1.1.5", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", @@ -22037,7 +22031,7 @@ }, "wp/headless-wp": { "name": "@headstartwp/headstartwp", - "version": "1.0.9", + "version": "1.0.10", "license": "GPL-2.0-or-later", "devDependencies": { "@wordpress/env": "^5.14.0" From 5bf90ccde0880a89bda159513de9b70b6597bd12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcholas=20Andr=C3=A9?= Date: Tue, 14 Nov 2023 23:22:25 -0300 Subject: [PATCH 2/3] Fix headless.config.js loading: preventing it from being injected multiple times. (#640) --- .changeset/fair-yaks-smash.md | 5 + package-lock.json | 66 +++++---- packages/next/package.json | 1 - .../ModifySourcePlugin/ModifySourcePlugin.ts | 139 ++++++++++++++++++ .../plugins/ModifySourcePlugin/index.ts | 2 + .../plugins/ModifySourcePlugin/loader.ts | 63 ++++++++ .../operations/AbstractOperation.ts | 15 ++ .../operations/ConcatOperation.ts | 27 ++++ .../operations/Operation.ts | 120 +++++++++++++++ .../operations/ReplaceOperation.ts | 28 ++++ .../ModifySourcePlugin/operations/index.ts | 4 + .../next/src/config/withHeadlessConfig.ts | 14 +- 12 files changed, 455 insertions(+), 29 deletions(-) create mode 100644 .changeset/fair-yaks-smash.md create mode 100644 packages/next/src/config/plugins/ModifySourcePlugin/ModifySourcePlugin.ts create mode 100644 packages/next/src/config/plugins/ModifySourcePlugin/index.ts create mode 100644 packages/next/src/config/plugins/ModifySourcePlugin/loader.ts create mode 100644 packages/next/src/config/plugins/ModifySourcePlugin/operations/AbstractOperation.ts create mode 100644 packages/next/src/config/plugins/ModifySourcePlugin/operations/ConcatOperation.ts create mode 100644 packages/next/src/config/plugins/ModifySourcePlugin/operations/Operation.ts create mode 100644 packages/next/src/config/plugins/ModifySourcePlugin/operations/ReplaceOperation.ts create mode 100644 packages/next/src/config/plugins/ModifySourcePlugin/operations/index.ts diff --git a/.changeset/fair-yaks-smash.md b/.changeset/fair-yaks-smash.md new file mode 100644 index 000000000..9e26032d3 --- /dev/null +++ b/.changeset/fair-yaks-smash.md @@ -0,0 +1,5 @@ +--- +"@headstartwp/next": patch +--- + +Fix loading of the headless.config.js file to prevent injecting it twice. diff --git a/package-lock.json b/package-lock.json index ef0f8436b..68e522798 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3381,6 +3381,7 @@ }, "node_modules/@jridgewell/source-map": { "version": "0.3.3", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -4862,6 +4863,7 @@ }, "node_modules/@types/eslint": { "version": "8.37.0", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -4871,6 +4873,7 @@ }, "node_modules/@types/eslint-scope": { "version": "3.7.4", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -4880,6 +4883,7 @@ }, "node_modules/@types/estree": { "version": "1.0.1", + "dev": true, "license": "MIT", "peer": true }, @@ -5025,6 +5029,7 @@ }, "node_modules/@types/node": { "version": "12.20.55", + "dev": true, "license": "MIT" }, "node_modules/@types/node-fetch": { @@ -5430,6 +5435,7 @@ }, "node_modules/@webassemblyjs/ast": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5439,16 +5445,19 @@ }, "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true }, @@ -5515,6 +5524,7 @@ }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5525,11 +5535,13 @@ }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5541,6 +5553,7 @@ }, "node_modules/@webassemblyjs/ieee754": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5549,6 +5562,7 @@ }, "node_modules/@webassemblyjs/leb128": { "version": "1.11.5", + "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { @@ -5557,11 +5571,13 @@ }, "node_modules/@webassemblyjs/utf8": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5577,6 +5593,7 @@ }, "node_modules/@webassemblyjs/wasm-gen": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5589,6 +5606,7 @@ }, "node_modules/@webassemblyjs/wasm-opt": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5600,6 +5618,7 @@ }, "node_modules/@webassemblyjs/wasm-parser": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5651,6 +5670,7 @@ }, "node_modules/@webassemblyjs/wast-printer": { "version": "1.11.5", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -5914,6 +5934,7 @@ }, "node_modules/acorn": { "version": "8.8.2", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -5933,6 +5954,7 @@ }, "node_modules/acorn-import-assertions": { "version": "1.8.0", + "dev": true, "license": "MIT", "peer": true, "peerDependencies": { @@ -8929,6 +8951,7 @@ }, "node_modules/es-module-lexer": { "version": "1.2.1", + "dev": true, "license": "MIT", "peer": true }, @@ -9500,6 +9523,7 @@ }, "node_modules/eslint-scope": { "version": "5.1.1", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -9511,6 +9535,7 @@ }, "node_modules/eslint-scope/node_modules/estraverse": { "version": "4.3.0", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -10966,6 +10991,7 @@ }, "node_modules/glob-to-regexp": { "version": "0.4.1", + "dev": true, "license": "BSD-2-Clause", "peer": true }, @@ -14661,6 +14687,7 @@ }, "node_modules/loader-runner": { "version": "4.3.0", + "dev": true, "license": "MIT", "peer": true, "engines": { @@ -14674,19 +14701,6 @@ "node": ">= 12.13.0" } }, - "node_modules/loader-utils-webpack-v4": { - "name": "loader-utils", - "version": "2.0.4", - "license": "MIT", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/locate-path": { "version": "6.0.0", "license": "MIT", @@ -15111,6 +15125,7 @@ }, "node_modules/merge-stream": { "version": "2.0.0", + "dev": true, "license": "MIT" }, "node_modules/merge2": { @@ -15340,17 +15355,6 @@ "node": ">=10" } }, - "node_modules/modify-source-webpack-plugin": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "loader-utils-webpack-v4": "npm:loader-utils@^2.0.4", - "schema-utils": "^4.0.0" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - } - }, "node_modules/move-concurrently": { "version": "1.0.1", "license": "ISC", @@ -18073,6 +18077,7 @@ }, "node_modules/serialize-javascript": { "version": "6.0.1", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" @@ -19396,6 +19401,7 @@ }, "node_modules/terser": { "version": "5.17.1", + "dev": true, "license": "BSD-2-Clause", "peer": true, "dependencies": { @@ -19413,6 +19419,7 @@ }, "node_modules/terser-webpack-plugin": { "version": "5.3.7", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -19446,6 +19453,7 @@ }, "node_modules/terser-webpack-plugin/node_modules/has-flag": { "version": "4.0.0", + "dev": true, "license": "MIT", "peer": true, "engines": { @@ -19454,6 +19462,7 @@ }, "node_modules/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -19467,6 +19476,7 @@ }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { "version": "3.1.2", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -19484,6 +19494,7 @@ }, "node_modules/terser-webpack-plugin/node_modules/supports-color": { "version": "8.1.1", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -19498,11 +19509,13 @@ }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", + "dev": true, "license": "MIT", "peer": true }, "node_modules/terser/node_modules/source-map-support": { "version": "0.5.21", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -20513,6 +20526,7 @@ }, "node_modules/watchpack": { "version": "2.4.0", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -20817,6 +20831,7 @@ }, "node_modules/webpack": { "version": "5.81.0", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -20977,6 +20992,7 @@ }, "node_modules/webpack-sources": { "version": "3.2.3", + "dev": true, "license": "MIT", "peer": true, "engines": { @@ -20985,6 +21001,7 @@ }, "node_modules/webpack/node_modules/schema-utils": { "version": "3.1.2", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -21758,7 +21775,6 @@ "@headstartwp/core": "^1.1.2", "deepmerge": "^4.3.1", "loader-utils": "^3.2.0", - "modify-source-webpack-plugin": "^4.1.0", "schema-utils": "^4.0.0" }, "devDependencies": { diff --git a/packages/next/package.json b/packages/next/package.json index a885f0d28..d2ff3058f 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -50,7 +50,6 @@ "dependencies": { "deepmerge": "^4.3.1", "@headstartwp/core": "^1.1.2", - "modify-source-webpack-plugin": "^4.1.0", "loader-utils": "^3.2.0", "schema-utils": "^4.0.0" }, diff --git a/packages/next/src/config/plugins/ModifySourcePlugin/ModifySourcePlugin.ts b/packages/next/src/config/plugins/ModifySourcePlugin/ModifySourcePlugin.ts new file mode 100644 index 000000000..5d5f65694 --- /dev/null +++ b/packages/next/src/config/plugins/ModifySourcePlugin/ModifySourcePlugin.ts @@ -0,0 +1,139 @@ +import type { Compiler, NormalModule, Compilation } from 'webpack'; + +import { AbstractOperation, Operation } from './operations'; + +const { validate } = require('schema-utils'); + +export interface Rule { + test: RegExp | ((module: NormalModule, compilation: Compilation) => boolean); + operations?: AbstractOperation[]; +} + +export type Options = { + debug?: boolean; + rules: Rule[]; + constants?: Record; +}; + +const validationSchema = { + type: 'object', + additionalProperties: false, + properties: { + rules: { + type: 'array', + items: { + type: 'object', + additionalProperties: false, + properties: { + test: { + anyOf: [{ instanceof: 'Function' }, { instanceof: 'RegExp' }], + }, + operations: { + type: 'array', + items: { + type: 'object', + }, + }, + }, + }, + }, + constants: { + type: 'object', + }, + debug: { + type: 'boolean', + }, + }, +}; + +const PLUGIN_NAME = 'ModifySourcePlugin'; + +export class ModifySourcePlugin { + constructor(protected readonly options: Options) { + validate(validationSchema, options, { + name: PLUGIN_NAME, + }); + } + + public apply(compiler: Compiler): void { + const { rules, debug, constants = {} } = this.options; + + compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { + const modifiedModules: (string | number)[] = []; + + const tapCallback = (_: any, normalModule: NormalModule) => { + const userRequest = normalModule.userRequest || ''; + + const startIndex = + userRequest.lastIndexOf('!') === -1 ? 0 : userRequest.lastIndexOf('!') + 1; + + const moduleRequest = userRequest.substring(startIndex).replace(/\\/g, '/'); + + if (modifiedModules.includes(moduleRequest)) { + return; + } + + rules.forEach((ruleOptions) => { + const { test } = ruleOptions; + const isMatched = (() => { + if (typeof test === 'function' && test(normalModule, compilation)) { + return true; + } + + return test instanceof RegExp && test.test(moduleRequest); + })(); + + if (isMatched) { + type NormalModuleLoader = { + loader: string; + options: any; + ident?: string; + type?: string; + }; + + const serializableOperations = ruleOptions.operations?.map((op) => + Operation.makeSerializable(op), + ); + + let loader; + + try { + loader = require.resolve('./loader.js'); + } catch (e) { + loader = require.resolve('../build/loader.js'); + } + + (normalModule.loaders as NormalModuleLoader[]).push({ + loader, + options: { + moduleRequest, + operations: serializableOperations, + constants, + }, + }); + + modifiedModules.push(moduleRequest); + + if (debug) { + // eslint-disable-next-line no-console + console.log(`\n[${PLUGIN_NAME}] Use loader for "${moduleRequest}".`); + } + } + }); + }; + + const NormalModule = compiler.webpack?.NormalModule; + const isNormalModuleAvailable = + Boolean(NormalModule) && Boolean(NormalModule.getCompilationHooks); + + if (isNormalModuleAvailable) { + NormalModule.getCompilationHooks(compilation).beforeLoaders.tap( + PLUGIN_NAME, + tapCallback, + ); + } else { + compilation.hooks.normalModuleLoader.tap(PLUGIN_NAME, tapCallback); + } + }); + } +} diff --git a/packages/next/src/config/plugins/ModifySourcePlugin/index.ts b/packages/next/src/config/plugins/ModifySourcePlugin/index.ts new file mode 100644 index 000000000..7787b76c9 --- /dev/null +++ b/packages/next/src/config/plugins/ModifySourcePlugin/index.ts @@ -0,0 +1,2 @@ +export * from './ModifySourcePlugin'; +export * from './operations'; diff --git a/packages/next/src/config/plugins/ModifySourcePlugin/loader.ts b/packages/next/src/config/plugins/ModifySourcePlugin/loader.ts new file mode 100644 index 000000000..db9e40cf3 --- /dev/null +++ b/packages/next/src/config/plugins/ModifySourcePlugin/loader.ts @@ -0,0 +1,63 @@ +import path from 'path'; + +import { Operation, SerializableOperation } from './operations'; + +const { validate } = require('schema-utils'); + +const schema = { + type: 'object', + properties: { + operations: { + type: 'array', + items: { + type: 'object', + }, + }, + moduleRequest: { + type: 'string', + }, + constants: { + type: 'object', + }, + }, + additionalProperties: false, +}; + +interface LoaderOptions { + operations: SerializableOperation[]; + moduleRequest: string; + constants: Record; +} + +interface modifyModuleSourceLoader { + getOptions: () => LoaderOptions; +} + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export default function modifyModuleSourceLoader( + this: modifyModuleSourceLoader, + source: string, +): string { + const options: LoaderOptions = this.getOptions(); + + validate(schema, options, { + name: 'ModifySourcePlugin webpack loader', + }); + + const cleanPath = options.moduleRequest.split('?')[0]; + const fileName = path.basename(cleanPath); + + if (source.includes('__setHeadstartWPConfig')) { + return source; + } + + return options.operations.reduce((sourceText, serializableOp) => { + const operation = Operation.fillConstants(Operation.fromSerializable(serializableOp), { + ...options.constants, + FILE_PATH: cleanPath, + FILE_NAME: fileName, + }); + + return Operation.apply(sourceText, operation); + }, source); +} diff --git a/packages/next/src/config/plugins/ModifySourcePlugin/operations/AbstractOperation.ts b/packages/next/src/config/plugins/ModifySourcePlugin/operations/AbstractOperation.ts new file mode 100644 index 000000000..9cb4bd99c --- /dev/null +++ b/packages/next/src/config/plugins/ModifySourcePlugin/operations/AbstractOperation.ts @@ -0,0 +1,15 @@ +export type SerializableProperties = { + [K in keyof T as T[K] extends string ? K : never]: T[K] extends string ? T[K] : never; +}; + +export type SerializableOperation = { + operationName: string; +} & { + [K in keyof T as T[K] extends string ? K : never]: T[K] extends string ? T[K] : never; +}; + +export abstract class AbstractOperation { + public abstract getSerializableProperties(): string[]; + + public abstract getTextProperties(): string[]; +} diff --git a/packages/next/src/config/plugins/ModifySourcePlugin/operations/ConcatOperation.ts b/packages/next/src/config/plugins/ModifySourcePlugin/operations/ConcatOperation.ts new file mode 100644 index 000000000..77a5b3a81 --- /dev/null +++ b/packages/next/src/config/plugins/ModifySourcePlugin/operations/ConcatOperation.ts @@ -0,0 +1,27 @@ +import { AbstractOperation } from './AbstractOperation'; + +export enum ConcatOperationType { + 'start' = 'start', + 'end' = 'end', +} + +export class ConcatOperation extends AbstractOperation { + constructor( + public readonly type: keyof typeof ConcatOperationType, + public readonly value: string, + ) { + super(); + } + + public getSerializableProperties(): (keyof this & string)[] { + return ['type', 'value']; + } + + public getTextProperties(): (keyof this & string)[] { + return ['value']; + } + + public static getAllowedTypes(): ConcatOperationType[] { + return [ConcatOperationType.start, ConcatOperationType.end]; + } +} diff --git a/packages/next/src/config/plugins/ModifySourcePlugin/operations/Operation.ts b/packages/next/src/config/plugins/ModifySourcePlugin/operations/Operation.ts new file mode 100644 index 000000000..d488b93fb --- /dev/null +++ b/packages/next/src/config/plugins/ModifySourcePlugin/operations/Operation.ts @@ -0,0 +1,120 @@ +import { + AbstractOperation, + SerializableOperation, + SerializableProperties, +} from './AbstractOperation'; +import { ConcatOperation } from './ConcatOperation'; +import { ReplaceOperation } from './ReplaceOperation'; + +function isSerializableOfOperation( + serializable: SerializableOperation, + operation: { new (...args: any[]): T }, +): serializable is SerializableOperation { + return serializable.operationName === operation.name; +} + +function throwUnknownOperationType(op: AbstractOperation, opType: string): void { + const allowedTypes = + op instanceof ConcatOperation + ? ConcatOperation.getAllowedTypes() + : ReplaceOperation.getAllowedTypes(); + + throw new Error( + `Incorrect operation type '${opType}' for ${ + op.constructor.name + }. Allowed types: '${allowedTypes.join("', '")}'.`, + ); +} + +export class Operation { + public static makeSerializable(op: T): SerializableOperation { + const propertyValues = op.getSerializableProperties().reduce((acc, val) => { + return { + ...acc, + [val]: op[val as keyof T], + }; + }, {} as SerializableProperties); + + return { + operationName: op.constructor.name, + ...propertyValues, + }; + } + + public static fromSerializable(serializable: SerializableOperation): AbstractOperation { + if (isSerializableOfOperation(serializable, ConcatOperation)) { + const { type, value } = serializable; + + return new ConcatOperation(type, value); + } + + if (isSerializableOfOperation(serializable, ReplaceOperation)) { + const { type, searchValue, replaceValue } = serializable; + + return new ReplaceOperation(type, searchValue, replaceValue); + } + + throw new Error(`Incorrect serializable provided: ${JSON.stringify(serializable)}`); + } + + public static fillConstants< + T extends AbstractOperation, + TConstants extends Record, + >(operation: T, constants: TConstants): T { + const filledTextProps = operation.getTextProperties().reduce((acc, propName) => { + let propValue = operation[propName as keyof T] as string; + + Object.keys(constants).forEach((constant) => { + propValue = propValue.replace( + new RegExp(`\\$${constant}`, 'g'), + String(constants[constant]), + ); + }); + + return { + ...acc, + [propName]: propValue, + }; + }, {}); + + const mergedObject = { + ...Operation.makeSerializable(operation), + ...filledTextProps, + }; + + return Operation.fromSerializable(mergedObject) as T; + } + + public static apply(src: string, operation: AbstractOperation): string { + if (operation instanceof ConcatOperation) { + switch (operation.type) { + case 'start': + return operation.value + src; + + case 'end': + return src + operation.value; + + default: + throwUnknownOperationType(operation, operation.type); + } + } + + if (operation instanceof ReplaceOperation) { + switch (operation.type) { + case 'once': + return src.replace(operation.searchValue, operation.replaceValue); + + case 'all': + return src.replace( + new RegExp(operation.searchValue, 'g'), + operation.replaceValue, + ); + + default: + throwUnknownOperationType(operation, operation.type); + } + } + + throw new Error(`Unknown operation instance: ${operation.constructor.name}`); + } +} diff --git a/packages/next/src/config/plugins/ModifySourcePlugin/operations/ReplaceOperation.ts b/packages/next/src/config/plugins/ModifySourcePlugin/operations/ReplaceOperation.ts new file mode 100644 index 000000000..38a56a793 --- /dev/null +++ b/packages/next/src/config/plugins/ModifySourcePlugin/operations/ReplaceOperation.ts @@ -0,0 +1,28 @@ +import { AbstractOperation } from './AbstractOperation'; + +export enum ReplaceOperationType { + 'once' = 'once', + 'all' = 'all', +} + +export class ReplaceOperation extends AbstractOperation { + constructor( + public readonly type: keyof typeof ReplaceOperationType, + public readonly searchValue: string, + public readonly replaceValue: string, + ) { + super(); + } + + public getSerializableProperties(): (keyof this & string)[] { + return ['type', 'searchValue', 'replaceValue']; + } + + public getTextProperties(): (keyof this & string)[] { + return ['searchValue', 'replaceValue']; + } + + public static getAllowedTypes(): ReplaceOperationType[] { + return [ReplaceOperationType.all, ReplaceOperationType.once]; + } +} diff --git a/packages/next/src/config/plugins/ModifySourcePlugin/operations/index.ts b/packages/next/src/config/plugins/ModifySourcePlugin/operations/index.ts new file mode 100644 index 000000000..d5848b6d5 --- /dev/null +++ b/packages/next/src/config/plugins/ModifySourcePlugin/operations/index.ts @@ -0,0 +1,4 @@ +export * from './AbstractOperation'; +export * from './ConcatOperation'; +export * from './ReplaceOperation'; +export * from './Operation'; diff --git a/packages/next/src/config/withHeadlessConfig.ts b/packages/next/src/config/withHeadlessConfig.ts index 0b08d7a5a..44a84a667 100644 --- a/packages/next/src/config/withHeadlessConfig.ts +++ b/packages/next/src/config/withHeadlessConfig.ts @@ -1,8 +1,8 @@ import { ConfigError, HeadlessConfig } from '@headstartwp/core'; import { NextConfig } from 'next'; -import { ModifySourcePlugin, ConcatOperation } from 'modify-source-webpack-plugin'; import path from 'path'; import fs from 'fs'; +import { ModifySourcePlugin, ConcatOperation } from './plugins/ModifySourcePlugin'; const LINARIA_EXTENSION = '.linaria.module.css'; @@ -153,9 +153,17 @@ export function withHeadlessConfig( }, webpack: (config, options) => { + const headlessConfigPath = `${process.cwd()}/headless.config.js`; + const headstartWpConfigPath = `${process.cwd()}/headstartwp.config.js`; + + const configPath = fs.existsSync(headstartWpConfigPath) + ? headstartWpConfigPath + : headlessConfigPath; + const importSetHeadlessConfig = ` - import { setHeadstartWPConfig } from '@headstartwp/core/utils'; - setHeadstartWPConfig(${JSON.stringify(headlessConfig)}); + import { setHeadstartWPConfig as __setHeadstartWPConfig } from '@headstartwp/core/utils'; + import __headlessConfig from '${configPath}'; + __setHeadstartWPConfig(__headlessConfig); `; // clear webpack cache whenever headless.config.js changes or one of the env files From 5a27a3f59de552eacc1cf870a440878d8e8cd2fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Nov 2023 09:56:34 -0300 Subject: [PATCH 3/3] Release (next) (#641) Co-authored-by: github-actions[bot] --- .changeset/pre.json | 19 +++++++++++++++++++ packages/next/CHANGELOG.md | 6 ++++++ packages/next/package.json | 2 +- .../wp-multisite-i18n-nextjs/package.json | 2 +- projects/wp-multisite-nextjs/package.json | 2 +- projects/wp-nextjs-ts/package.json | 2 +- projects/wp-nextjs/package.json | 2 +- 7 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 .changeset/pre.json diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..5e5509b3e --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,19 @@ +{ + "mode": "pre", + "tag": "next", + "initialVersions": { + "@headstartwp/core": "1.1.2", + "@10up/react-hooks": "1.2.3", + "@headstartwp/next": "1.1.5", + "@10up/next-redis-cache-provider": "0.1.5", + "@10up/headless-docs": "1.0.0", + "@10up/wp-multisite-i18n-nextjs": "0.2.0", + "@10up/wp-multisite-nextjs": "0.2.0", + "@10up/wp-nextjs": "0.2.0", + "@10up/wp-nextjs-ts": "0.2.1-next.2", + "@headstartwp/headstartwp": "1.0.10" + }, + "changesets": [ + "fair-yaks-smash" + ] +} diff --git a/packages/next/CHANGELOG.md b/packages/next/CHANGELOG.md index a8fdc57b5..1463db200 100644 --- a/packages/next/CHANGELOG.md +++ b/packages/next/CHANGELOG.md @@ -1,5 +1,11 @@ # @headstartwp/next +## 1.1.6-next.0 + +### Patch Changes + +- 5bf90ccd: Fix loading of the headless.config.js file to prevent injecting it twice. + ## 1.1.5 ### Patch Changes diff --git a/packages/next/package.json b/packages/next/package.json index d2ff3058f..cd283ed62 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "@headstartwp/next", - "version": "1.1.5", + "version": "1.1.6-next.0", "description": "`@headstartwp/next` is the Next.js bindings for the headless framework.", "homepage": "https://github.com/10up/headstartwp/blob/develop/packages/next/README.md", "license": "MIT", diff --git a/projects/wp-multisite-i18n-nextjs/package.json b/projects/wp-multisite-i18n-nextjs/package.json index 05232507e..aaf2a2d03 100644 --- a/projects/wp-multisite-i18n-nextjs/package.json +++ b/projects/wp-multisite-i18n-nextjs/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@headstartwp/core": "^1.1.2", - "@headstartwp/next": "^1.1.5", + "@headstartwp/next": "^1.1.6-next.0", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", diff --git a/projects/wp-multisite-nextjs/package.json b/projects/wp-multisite-nextjs/package.json index c9a592a80..b9a72d292 100644 --- a/projects/wp-multisite-nextjs/package.json +++ b/projects/wp-multisite-nextjs/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@headstartwp/core": "^1.1.2", - "@headstartwp/next": "^1.1.5", + "@headstartwp/next": "^1.1.6-next.0", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", diff --git a/projects/wp-nextjs-ts/package.json b/projects/wp-nextjs-ts/package.json index 261f54532..0ab140b6c 100644 --- a/projects/wp-nextjs-ts/package.json +++ b/projects/wp-nextjs-ts/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@headstartwp/core": "^1.1.2", - "@headstartwp/next": "^1.1.5", + "@headstartwp/next": "^1.1.6-next.0", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", diff --git a/projects/wp-nextjs/package.json b/projects/wp-nextjs/package.json index 4e9a93732..2aa36d774 100644 --- a/projects/wp-nextjs/package.json +++ b/projects/wp-nextjs/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@headstartwp/core": "^1.1.2", - "@headstartwp/next": "^1.1.5", + "@headstartwp/next": "^1.1.6-next.0", "@10up/next-redis-cache-provider": "^0.1.5", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10",