diff --git a/src/main/resources/lib/enonic/react4xp/DataFetcher.ts b/src/main/resources/lib/enonic/react4xp/DataFetcher.ts index 357f675e..07d31a98 100644 --- a/src/main/resources/lib/enonic/react4xp/DataFetcher.ts +++ b/src/main/resources/lib/enonic/react4xp/DataFetcher.ts @@ -51,7 +51,7 @@ import { import { getCachedPageComponentFromContentType } from '/lib/enonic/react4xp/pageTemplate/getCachedPageComponentFromContentType'; import { getCachedPageComponentFromPageTemplateContentId } from '/lib/enonic/react4xp/pageTemplate/getCachedPageComponentFromPageTemplateContentId'; -import {replaceMacroComments} from './replaceMacroComments'; +import { dataFromProcessedHtml } from '/lib/enonic/react4xp/dataFromProcessedHtml'; export type FragmentContent< @@ -515,7 +515,7 @@ export class DataFetcher { const processedHtml = processHtml({ value: html }); - const data = replaceMacroComments(processedHtml); + const data = dataFromProcessedHtml(processedHtml); setIn(processedComponent, path, data); } } // for @@ -545,7 +545,7 @@ export class DataFetcher { }); const renderableTextComponent: RenderableTextComponent = JSON.parse(JSON.stringify(component)); renderableTextComponent.props = { - data: replaceMacroComments(processedHtml), + data: dataFromProcessedHtml(processedHtml), mode }; return renderableTextComponent; @@ -586,7 +586,7 @@ export class DataFetcher { const processedHtml = processHtml({ value: html }); - const data = replaceMacroComments(processedHtml); + const data = dataFromProcessedHtml(processedHtml); setIn(processedLayoutOrPageComponent, path, data); } } // for diff --git a/src/main/resources/lib/enonic/react4xp/dataFromProcessedHtml.ts b/src/main/resources/lib/enonic/react4xp/dataFromProcessedHtml.ts new file mode 100644 index 00000000..4dfcc074 --- /dev/null +++ b/src/main/resources/lib/enonic/react4xp/dataFromProcessedHtml.ts @@ -0,0 +1,115 @@ +import type { + ImageContent, + ImageData, + MacroData, + RichTextData +} from '@enonic/react-components'; +import {get as getContentByKey} from '/lib/xp/content'; + + +export function dataFromProcessedHtml(processedHtml: string): RichTextData { + const rv: RichTextData = { + processedHtml, + macros: [], + images: [], + links: [], + }; + let index = 0; + rv.processedHtml = processedHtml + .replace( + /

()<\/p>/gm, + '$1' + ) + .replace( + /

()<\/pre>/gm,
+			'$1'
+		)
+		.replace(
+			//gm,
+			(_origHtmlMacroComment, attributesString) => {
+				// Replacer is executed once per match (macro comment)
+				index++;
+				const ref = index.toString();
+				let name: string = '';
+				const macro: Partial = {
+					config: {},
+					ref,
+				};
+				const replacedAttributes = attributesString.replace(
+					/([^=]+)="([^"]*)"\s*/g,
+					(_kv, key, value) => {
+						// Replacer is executed once per match (attribute key/value)
+						if (key === '_name') {
+							name = value;
+							macro.name = name;
+							macro.descriptor = `whatever:${name}`;
+							return `data-macro-name="${value}" data-macro-ref="${ref}"`;
+						}
+						if (key === '_document') {
+							return '';
+						}
+						if (key === '_body') {
+							key = 'body';
+						}
+						if (macro.config && name) {
+							if (!macro.config[name]) {
+								macro.config[name] = {};
+							}
+							macro.config[name][key] = value;
+						}
+						return '';
+					}
+				)
+				const replacedMacro = ``;
+				if (rv.macros) {
+					rv.macros.push(macro as MacroData);
+				}
+				return replacedMacro;
+			} // single macro replacer
+		);
+
+		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
+	// If the g flag is used, all results matching the complete regular expression will be returned, but capturing groups are not included.
+	rv.processedHtml = rv.processedHtml.replace(//gm,
+		(_origImgString, imgAttributesString) => {
+			// Replacer is executed once per match (img element)
+			index++;
+			const ref = index.toString();
+
+			const srcMatches = imgAttributesString.match(/src="((?:.*?\n?)*?)"/m);
+			if (!srcMatches) {
+				throw new Error(`No src attribute found in imgAttributesString:${imgAttributesString}!`);
+			}
+			const [_fullSrc, src] = srcMatches;
+			// (log||console).debug('src:%s', src);
+
+			const idMatches = src.match(/_\/image\/([0-9a-f-]+)/);
+			// (log||console).debug('idMatches:%s', idMatches);
+
+			if (!idMatches) {
+				throw new Error(`No image id found in src:${src}!`);
+			}
+			const [_fullId, imageContentId] = idMatches;
+			// (log||console).debug('imageContentId:%s', imageContentId);
+
+			const imageContent: ImageContent = getContentByKey({ key: imageContentId });
+			if (!imageContent) {
+				throw new Error(`No image content found for id:${imageContentId}!`);
+			}
+			// (log||console).debug('imageContent:%s', imageContent);
+
+			const image = {
+				image: imageContent,
+				ref,
+				// style: null // TODO
+			};
+			rv.images.push(image as ImageData);
+			const replacedImage = ``;
+			// (log||console).debug('replacedImage:%s', replacedImage);
+			return replacedImage;
+		});
+
+	// NOTE content-links seems to work fine without any special handling
+
+	return rv;
+}
diff --git a/src/main/resources/lib/enonic/react4xp/replaceMacroComments.ts b/src/main/resources/lib/enonic/react4xp/replaceMacroComments.ts
deleted file mode 100644
index cea78da4..00000000
--- a/src/main/resources/lib/enonic/react4xp/replaceMacroComments.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import type {
-	MacroData,
-	RichTextData
-} from '@enonic/react-components';
-
-export function replaceMacroComments(processedHtml: string): RichTextData {
-	const rv: RichTextData = {
-		processedHtml,
-		macros: []
-	};
-	let index = 0;
-	rv.processedHtml = processedHtml
-		.replace(
-			/

()<\/p>/gm, - '$1' - ) - .replace( - /

()<\/pre>/gm,
-			'$1'
-		)
-		.replace(
-			//gm,
-			(_origHtmlMacroComment, attributesString) => {
-				// Replacer is executed once per match (macro comment)
-				index++;
-				const ref = index.toString();
-				let name: string = '';
-				const macro: Partial = {
-					config: {},
-					ref,
-				};
-				const replacedAttributes = attributesString.replace(
-					/([^=]+)="([^"]*)"\s*/g,
-					(_kv, key, value) => {
-						// Replacer is executed once per match (attribute key/value)
-						if (key === '_name') {
-							name = value;
-							macro.name = name;
-							macro.descriptor = `whatever:${name}`;
-							return `data-macro-name="${value}" data-macro-ref="${ref}"`;
-						}
-						if (key === '_document') {
-							return '';
-						}
-						if (key === '_body') {
-							key = 'body';
-						}
-						if (macro.config && name) {
-							if (!macro.config[name]) {
-								macro.config[name] = {};
-							}
-							macro.config[name][key] = value;
-						}
-						return '';
-					}
-				)
-				const replacedMacro = ``;
-				if (rv.macros) {
-					rv.macros.push(macro as MacroData);
-				}
-				return replacedMacro;
-			} // single macro replacer
-		);
-	return rv;
-}