Skip to content

Commit 289f078

Browse files
committed
Merge remote-tracking branch 'origin/trunk' into update/local-translations
2 parents 9080b7b + b29be00 commit 289f078

14 files changed

+107
-17
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Significance: patch
2+
Type: added
3+
Comment: Added utility functions
4+
5+

projects/js-packages/ai-client/src/hooks/use-post-content.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,24 @@ const usePostContent = () => {
2828
};
2929
}, [] );
3030

31+
const getSerializedPostContent = useCallback( () => {
32+
const blocks = getBlocks();
33+
34+
if ( blocks.length === 0 ) {
35+
return '';
36+
}
37+
38+
return serialize( blocks );
39+
}, [ getBlocks ] );
40+
3141
const getPostContent = useCallback(
3242
( preprocess?: ( serialized: string ) => string ) => {
33-
const blocks = getBlocks();
43+
let serialized = getSerializedPostContent();
3444

35-
if ( blocks.length === 0 ) {
45+
if ( ! serialized ) {
3646
return '';
3747
}
3848

39-
let serialized = serialize( blocks );
40-
4149
if ( preprocess && typeof preprocess === 'function' ) {
4250
serialized = preprocess( serialized );
4351
}
@@ -47,7 +55,7 @@ const usePostContent = () => {
4755
[ getBlocks ]
4856
);
4957

50-
return { getPostContent, isEditedPostEmpty };
58+
return { getPostContent, isEditedPostEmpty, getSerializedPostContent };
5159
};
5260

5361
export default usePostContent;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { select } from '@wordpress/data';
5+
/**
6+
* Internal dependencies
7+
*/
8+
import type { Block } from '../types.js';
9+
10+
/**
11+
* Recursively get all blocks from the post, including nested innerBlocks
12+
* @return {Array} Array of all blocks in the post
13+
*/
14+
export const getAllBlocks = (): Array< Block > => {
15+
const topLevelBlocks = select( 'core/block-editor' ).getBlocks();
16+
const allBlocks: Array< Block > = [];
17+
18+
const processBlock = ( block: Block ) => {
19+
allBlocks.push( block );
20+
21+
if ( block.innerBlocks?.length ) {
22+
block.innerBlocks.forEach( processBlock );
23+
}
24+
};
25+
26+
topLevelBlocks.forEach( processBlock );
27+
28+
return allBlocks;
29+
};

projects/js-packages/ai-client/src/libs/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ export { mapActionToHumanText } from './map-action-to-human-text.js';
1313
export { openBlockSidebar } from './open-block-sidebar.js';
1414

1515
export { showAiAssistantSection } from './show-ai-assistant-section.js';
16+
17+
export { getAllBlocks } from './get-all-blocks.js';
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: other
3+
4+
JSON API: activate REST for posts fetching endpoint.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: other
3+
4+
AI Assistant: Add image index information on caption generation request
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: other
3+
4+
Newsletter Widget: hint dashboard placement for widget to be 2nd column, near the top

projects/plugins/jetpack/class-jetpack-newsletter-dashboard-widget.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,12 @@ public static function wp_dashboard_setup() {
107107
wp_add_dashboard_widget(
108108
self::$widget_id,
109109
$widget_title,
110-
array( static::class, 'render' )
110+
array( static::class, 'render' ),
111+
// @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- Core should ideally document null for no-callback arg. https://core.trac.wordpress.org/ticket/52539.
112+
null,
113+
array(),
114+
'side',
115+
'high'
111116
);
112117
}
113118
}

projects/plugins/jetpack/class.json-api-endpoints.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2820,7 +2820,9 @@ final public function rest_permission_callback() {
28202820
return new WP_Error( 'site_not_connected' );
28212821
}
28222822

2823-
if ( ( $this->allow_jetpack_site_auth && Rest_Authentication::is_signed_with_blog_token() ) || ( get_current_user_id() && Rest_Authentication::is_signed_with_user_token() ) ) {
2823+
if ( ( ( $this->allow_jetpack_site_auth || $this->allow_fallback_to_jetpack_blog_token ) && Rest_Authentication::is_signed_with_blog_token() )
2824+
|| ( get_current_user_id() && Rest_Authentication::is_signed_with_user_token() )
2825+
) {
28242826
$custom_permission_result = $this->rest_permission_callback_custom();
28252827

28262828
// Successful custom permission check.

projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/image/with-ai-image-extension.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,16 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => {
137137
startLoading( type );
138138

139139
try {
140+
const context: { positions?: number[] } = {};
141+
140142
if ( type === TYPE_ALT_TEXT ) {
141143
openBlockSidebar( props.clientId );
142144
}
143145

146+
if ( type === TYPE_CAPTION ) {
147+
context.positions = [ props.clientId ];
148+
}
149+
144150
dequeueAsyncRequest();
145151

146152
const response = await askQuestionSync(
@@ -150,8 +156,7 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => {
150156
context: {
151157
type: type,
152158
content: getPostContent( preprocessImageContent ),
153-
// URL of the image for the AI to find where the image is in the post.
154-
urls: [ props.attributes.url ],
159+
...context,
155160
images: [
156161
{
157162
// We convert the image to a base64 string to avoid inaccesible URLs for private images.
@@ -169,7 +174,11 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => {
169174

170175
increaseRequestsCount();
171176

172-
const parsedResponse: { texts?: string[]; captions?: string[] } = JSON.parse( response );
177+
const parsedResponse: { texts?: string[]; captions?: string[] } = JSON.parse(
178+
response
179+
?.replace?.( /^```json\s*/, '' ) // Remove the markdown code block if it exists.
180+
?.replace( /```$/, '' )
181+
);
173182

174183
if ( type === TYPE_ALT_TEXT ) {
175184
const alt = parsedResponse.texts?.[ 0 ];

projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/lib/preprocess-image-content.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
11
/**
2-
* Preprocess the serialized post content to remove image URLs and alt text, adding a unique count to each image.
3-
* This is used to ensure that the AI is not confused by the URLs in the post content.
2+
* External dependencies
3+
*/
4+
import { getAllBlocks } from '@automattic/jetpack-ai-client';
5+
6+
/**
7+
* Preprocess the serialized post content to remove image captions and alt text, changing the image urls to their clientId.
8+
* This is used to ensure that the AI is not confused by URLs in the post content, while still being able to identify the image blocks.
49
* @param {string} content - The content to preprocess.
510
* @return {string} The preprocessed content.
611
*/
712
export const preprocessImageContent = ( content: string ): string => {
8-
let imageCounter = 0;
13+
const imageBlocks = getAllBlocks().filter( block => block.name === 'core/image' );
14+
let currentImageIndex = 0;
915

1016
// Remove figcaption elements
1117
content = content.replace( /<figcaption[^>]*>.*?<\/figcaption>/g, '' );
1218

13-
// Replace image URLs with a unique count and remove alt text
14-
content = content.replace( /<img[^>]*>/g, () => {
15-
imageCounter++;
19+
// Replace the urls of images within image blocks with their clientId
20+
content = content.replace( /<!-- wp:image[^>]*>.*?<img[^>]*>.*?<!-- \/wp:image -->/gs, () => {
21+
// The assumption here is that the image blocks are always in the same order as the images in the post's HTML content
22+
const imageBlock = imageBlocks[ currentImageIndex ];
23+
currentImageIndex++;
24+
25+
if ( ! imageBlock ) {
26+
return '';
27+
}
1628

17-
return `<img src="image-${ imageCounter }">`;
29+
return `<img src="${ imageBlock.clientId }">`;
1830
} );
1931

2032
return content;

projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-posts-endpoint.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
'path_labels' => array(
1717
'$site' => '(int|string) Site ID or domain',
1818
),
19+
'rest_route' => '/posts',
20+
'rest_min_jp_version' => '14.5-a.1',
1921

2022
'allow_fallback_to_jetpack_blog_token' => true,
2123

projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-posts-v1-1-endpoint.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
'path_labels' => array(
1818
'$site' => '(int|string) Site ID or domain',
1919
),
20+
'rest_route' => '/posts',
21+
'rest_min_jp_version' => '14.5-a.1',
2022

2123
'allow_fallback_to_jetpack_blog_token' => true,
2224

projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-posts-v1-2-endpoint.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
'path_labels' => array(
1818
'$site' => '(int|string) Site ID or domain',
1919
),
20+
'rest_route' => '/posts',
21+
'rest_min_jp_version' => '14.5-a.1',
2022

2123
'allow_fallback_to_jetpack_blog_token' => true,
2224

0 commit comments

Comments
 (0)