@automattic/jetpack-ai-client 0.12.1 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.12.2] - 2024-04-22
9
+ ### Added
10
+ - AI Client: Add Markdown and HTML conversions. [#36906]
11
+
8
12
  ## [0.12.1] - 2024-04-15
9
13
  ### Added
10
14
  - AI Client: Add callbacks, initial requesting state and change error handling. [#36869]
@@ -286,6 +290,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
286
290
  - Updated package dependencies. [#31659]
287
291
  - Updated package dependencies. [#31785]
288
292
 
293
+ [0.12.2]: https://github.com/Automattic/jetpack-ai-client/compare/v0.12.1...v0.12.2
289
294
  [0.12.1]: https://github.com/Automattic/jetpack-ai-client/compare/v0.12.0...v0.12.1
290
295
  [0.12.0]: https://github.com/Automattic/jetpack-ai-client/compare/v0.11.0...v0.12.0
291
296
  [0.11.0]: https://github.com/Automattic/jetpack-ai-client/compare/v0.10.1...v0.11.0
package/build/index.d.ts CHANGED
@@ -12,3 +12,4 @@ export * from './icons/index.js';
12
12
  export * from './components/index.js';
13
13
  export * from './data-flow/index.js';
14
14
  export * from './types.js';
15
+ export * from './libs/index.js';
package/build/index.js CHANGED
@@ -30,3 +30,7 @@ export * from './data-flow/index.js';
30
30
  * Types
31
31
  */
32
32
  export * from './types.js';
33
+ /*
34
+ * Libs
35
+ */
36
+ export * from './libs/index.js';
@@ -0,0 +1 @@
1
+ export { MarkdownToHTML, HTMLToMarkdown, renderHTMLFromMarkdown, renderMarkdownFromHTML, } from './markdown/index.js';
@@ -0,0 +1 @@
1
+ export { MarkdownToHTML, HTMLToMarkdown, renderHTMLFromMarkdown, renderMarkdownFromHTML, } from './markdown/index.js';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import TurndownService from 'turndown';
5
+ /**
6
+ * Types
7
+ */
8
+ import type { Options, Rule } from 'turndown';
9
+ export default class HTMLToMarkdown {
10
+ turndownService: TurndownService;
11
+ constructor(options?: Options, rules?: {
12
+ [key: string]: Rule;
13
+ });
14
+ /**
15
+ * Renders HTML from Markdown content with specified processing rules.
16
+ * @param {object} options - The options to use when rendering the Markdown content
17
+ * @param {string} options.content - The HTML content to render
18
+ * @returns {string} The rendered Markdown content
19
+ */
20
+ render({ content }: {
21
+ content: string;
22
+ }): string;
23
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import TurndownService from 'turndown';
5
+ const defaultTurndownOptions = { emDelimiter: '_', headingStyle: 'atx' };
6
+ const defaultTurndownRules = {
7
+ strikethrough: {
8
+ filter: ['del', 's'],
9
+ replacement: function (content) {
10
+ return '~~' + content + '~~';
11
+ },
12
+ },
13
+ };
14
+ export default class HTMLToMarkdown {
15
+ turndownService;
16
+ constructor(options = defaultTurndownOptions, rules = defaultTurndownRules) {
17
+ this.turndownService = new TurndownService(options);
18
+ for (const rule in rules) {
19
+ this.turndownService.addRule(rule, rules[rule]);
20
+ }
21
+ }
22
+ /**
23
+ * Renders HTML from Markdown content with specified processing rules.
24
+ * @param {object} options - The options to use when rendering the Markdown content
25
+ * @param {string} options.content - The HTML content to render
26
+ * @returns {string} The rendered Markdown content
27
+ */
28
+ render({ content }) {
29
+ return this.turndownService.turndown(content);
30
+ }
31
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import HTMLToMarkdown from './html-to-markdown.js';
5
+ import MarkdownToHTML from './markdown-to-html.js';
6
+ /**
7
+ * Types
8
+ */
9
+ import type { Fix as HTMLFix } from './markdown-to-html.js';
10
+ declare const renderHTMLFromMarkdown: ({ content, rules, }: {
11
+ content: string;
12
+ rules?: Array<HTMLFix> | 'all';
13
+ }) => string;
14
+ declare const renderMarkdownFromHTML: ({ content }: {
15
+ content: string;
16
+ }) => string;
17
+ export { MarkdownToHTML, HTMLToMarkdown, renderHTMLFromMarkdown, renderMarkdownFromHTML };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import HTMLToMarkdown from './html-to-markdown.js';
5
+ import MarkdownToHTML from './markdown-to-html.js';
6
+ const defaultMarkdownConverter = new MarkdownToHTML();
7
+ const defaultHTMLConverter = new HTMLToMarkdown();
8
+ const renderHTMLFromMarkdown = ({ content, rules = 'all', }) => {
9
+ return defaultMarkdownConverter.render({ content, rules });
10
+ };
11
+ const renderMarkdownFromHTML = ({ content }) => {
12
+ return defaultHTMLConverter.render({ content });
13
+ };
14
+ export { MarkdownToHTML, HTMLToMarkdown, renderHTMLFromMarkdown, renderMarkdownFromHTML };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import MarkdownIt from 'markdown-it';
5
+ /**
6
+ * Types
7
+ */
8
+ import type { Options } from 'markdown-it';
9
+ export type Fix = 'list';
10
+ export default class MarkdownToHTML {
11
+ markdownConverter: MarkdownIt;
12
+ constructor(options?: Options);
13
+ /**
14
+ * Renders HTML from Markdown content with specified processing rules.
15
+ * @param {object} options - The options to use when rendering the HTML content
16
+ * @param {string} options.content - The Markdown content to render
17
+ * @param {string} options.rules - The rules to apply to the rendered content
18
+ * @returns {string} The rendered HTML content
19
+ */
20
+ render({ content, rules }: {
21
+ content: string;
22
+ rules: Array<Fix> | 'all';
23
+ }): string;
24
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import MarkdownIt from 'markdown-it';
5
+ const fixes = {
6
+ list: (content) => {
7
+ // Fix list indentation
8
+ return content.replace(/<li>\s+<p>/g, '<li>').replace(/<\/p>\s+<\/li>/g, '</li>');
9
+ },
10
+ };
11
+ const defaultMarkdownItOptions = {
12
+ breaks: true,
13
+ };
14
+ export default class MarkdownToHTML {
15
+ markdownConverter;
16
+ constructor(options = defaultMarkdownItOptions) {
17
+ this.markdownConverter = new MarkdownIt(options);
18
+ }
19
+ /**
20
+ * Renders HTML from Markdown content with specified processing rules.
21
+ * @param {object} options - The options to use when rendering the HTML content
22
+ * @param {string} options.content - The Markdown content to render
23
+ * @param {string} options.rules - The rules to apply to the rendered content
24
+ * @returns {string} The rendered HTML content
25
+ */
26
+ render({ content, rules = 'all' }) {
27
+ const rendered = this.markdownConverter.render(content);
28
+ const rulesToApply = rules === 'all' ? Object.keys(fixes) : rules;
29
+ return rulesToApply.reduce((renderedContent, rule) => {
30
+ return fixes[rule](renderedContent);
31
+ }, rendered);
32
+ }
33
+ }
package/build/types.d.ts CHANGED
@@ -28,4 +28,14 @@ export type { RecordingState } from './hooks/use-media-recording/index.js';
28
28
  export type CancelablePromise<T = void> = Promise<T> & {
29
29
  canceled?: boolean;
30
30
  };
31
+ export type Block = {
32
+ attributes?: {
33
+ [key: string]: unknown;
34
+ };
35
+ clientId?: string;
36
+ innerBlocks?: Block[];
37
+ isValid?: boolean;
38
+ name?: string;
39
+ originalContent?: string;
40
+ };
31
41
  export type TranscriptionState = RecordingState | 'validating' | 'processing' | 'error';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@automattic/jetpack-ai-client",
4
- "version": "0.12.1",
4
+ "version": "0.12.2",
5
5
  "description": "A JS client for consuming Jetpack AI services",
6
6
  "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/ai-client/#readme",
7
7
  "bugs": {
@@ -26,6 +26,8 @@
26
26
  "@storybook/addon-actions": "8.0.6",
27
27
  "@storybook/blocks": "8.0.6",
28
28
  "@storybook/react": "8.0.6",
29
+ "@types/markdown-it": "14.0.0",
30
+ "@types/turndown": "5.0.4",
29
31
  "jest": "^29.6.2",
30
32
  "jest-environment-jsdom": "29.7.0",
31
33
  "typescript": "5.0.4"
@@ -54,7 +56,9 @@
54
56
  "@wordpress/icons": "9.46.0",
55
57
  "classnames": "2.3.2",
56
58
  "debug": "4.3.4",
59
+ "markdown-it": "14.0.0",
57
60
  "react": "18.2.0",
58
- "react-dom": "18.2.0"
61
+ "react-dom": "18.2.0",
62
+ "turndown": "7.1.2"
59
63
  }
60
64
  }
package/src/index.ts CHANGED
@@ -35,3 +35,8 @@ export * from './data-flow/index.js';
35
35
  * Types
36
36
  */
37
37
  export * from './types.js';
38
+
39
+ /*
40
+ * Libs
41
+ */
42
+ export * from './libs/index.js';
@@ -0,0 +1,6 @@
1
+ export {
2
+ MarkdownToHTML,
3
+ HTMLToMarkdown,
4
+ renderHTMLFromMarkdown,
5
+ renderMarkdownFromHTML,
6
+ } from './markdown/index.js';
@@ -0,0 +1,74 @@
1
+ # Markdown converters
2
+
3
+ Typescript functions and classes to convert Markdown to and from HTML.
4
+
5
+ ## HTML to Markdown
6
+
7
+ The HTML to Markdown conversion uses the [Turndown](https://github.com/mixmark-io/turndown) library and supports Turndown's options and rules.
8
+
9
+ Example:
10
+ ```typescript
11
+ /**
12
+ * External dependencies
13
+ */
14
+ import { renderMarkdownFromHTML } from '@automattic/jetpack-ai-client';
15
+
16
+ const htmlContent = '<strong>Hello world</strong>';
17
+ const markdownContent = renderMarkdownFromHTML( { content: htmlContent } );
18
+ // **Hello world**
19
+ ```
20
+
21
+ To use custom options and rules:
22
+ ```typescript
23
+ /**
24
+ * External dependencies
25
+ */
26
+ import { HTMLToMarkdown } from '@automattic/jetpack-ai-client';
27
+
28
+ const htmlContent = '<strong>Hello world</strong>';
29
+ const options = { headingStyle: 'setext' };
30
+ const rules = {
31
+ customStrong: {
32
+ filter: [ 'strong' ],
33
+ replacement: function( content: string ) {
34
+ return '***' + content + '***';
35
+ }
36
+ }
37
+ };
38
+ const renderer = new HTMLToMarkdown( options, rules );
39
+ const markdownContent = renderer.render( { content: htmlContent } );
40
+ // ***Hello world***
41
+ ```
42
+
43
+ ## Markdown to HTML
44
+
45
+ The Markdown to HTML conversion uses the [markdown-it](https://github.com/markdown-it/markdown-it) library and supports markdown-it's options. It also adds access to common fixes.
46
+
47
+ Example:
48
+ ```typescript
49
+ /**
50
+ * External dependencies
51
+ */
52
+ import { renderHTMLFromMarkdown } from '@automattic/jetpack-ai-client';
53
+
54
+ const markdownContent = '**Hello world**';
55
+ const htmlContent = renderHTMLFromMarkdown( { content: markdownContent, rules: 'all' } ); // 'all' is a default value
56
+ // <p><strong>Hello world</strong></p>\n
57
+ ```
58
+
59
+ To use custom options and fixes:
60
+ ```typescript
61
+ /**
62
+ * External dependencies
63
+ */
64
+ import { MarkdownToHTML } from '@automattic/jetpack-ai-client';
65
+
66
+ const markdownContent = '**Hello world**';
67
+ const options = { breaks: 'false' };
68
+ const rules = [ 'list' ];
69
+ const renderer = new MarkdownToHTML( options );
70
+ const htmlContent = renderer.render( { content: markdownContent, rules } );
71
+ // <p><strong>Hello world</strong></p>\n
72
+ ```
73
+
74
+ Currently `rules` only supports `'all'` and `['list']`. Further specific fixes can be added when necessary.
@@ -0,0 +1,42 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import TurndownService from 'turndown';
5
+ /**
6
+ * Types
7
+ */
8
+ import type { Options, Rule } from 'turndown';
9
+
10
+ const defaultTurndownOptions: Options = { emDelimiter: '_', headingStyle: 'atx' };
11
+ const defaultTurndownRules: { [ key: string ]: Rule } = {
12
+ strikethrough: {
13
+ filter: [ 'del', 's' ],
14
+ replacement: function ( content: string ) {
15
+ return '~~' + content + '~~';
16
+ },
17
+ },
18
+ };
19
+
20
+ export default class HTMLToMarkdown {
21
+ turndownService: TurndownService;
22
+
23
+ constructor(
24
+ options: Options = defaultTurndownOptions,
25
+ rules: { [ key: string ]: Rule } = defaultTurndownRules
26
+ ) {
27
+ this.turndownService = new TurndownService( options );
28
+ for ( const rule in rules ) {
29
+ this.turndownService.addRule( rule, rules[ rule ] );
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Renders HTML from Markdown content with specified processing rules.
35
+ * @param {object} options - The options to use when rendering the Markdown content
36
+ * @param {string} options.content - The HTML content to render
37
+ * @returns {string} The rendered Markdown content
38
+ */
39
+ render( { content }: { content: string } ): string {
40
+ return this.turndownService.turndown( content );
41
+ }
42
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import HTMLToMarkdown from './html-to-markdown.js';
5
+ import MarkdownToHTML from './markdown-to-html.js';
6
+ /**
7
+ * Types
8
+ */
9
+ import type { Fix as HTMLFix } from './markdown-to-html.js';
10
+
11
+ const defaultMarkdownConverter = new MarkdownToHTML();
12
+ const defaultHTMLConverter = new HTMLToMarkdown();
13
+
14
+ const renderHTMLFromMarkdown = ( {
15
+ content,
16
+ rules = 'all',
17
+ }: {
18
+ content: string;
19
+ rules?: Array< HTMLFix > | 'all';
20
+ } ) => {
21
+ return defaultMarkdownConverter.render( { content, rules } );
22
+ };
23
+
24
+ const renderMarkdownFromHTML = ( { content }: { content: string } ) => {
25
+ return defaultHTMLConverter.render( { content } );
26
+ };
27
+
28
+ export { MarkdownToHTML, HTMLToMarkdown, renderHTMLFromMarkdown, renderMarkdownFromHTML };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import MarkdownIt from 'markdown-it';
5
+ /**
6
+ * Types
7
+ */
8
+ import type { Options } from 'markdown-it';
9
+
10
+ export type Fix = 'list';
11
+ type Fixes = {
12
+ [ key in Fix ]: ( content: string ) => string;
13
+ };
14
+
15
+ const fixes: Fixes = {
16
+ list: ( content: string ) => {
17
+ // Fix list indentation
18
+ return content.replace( /<li>\s+<p>/g, '<li>' ).replace( /<\/p>\s+<\/li>/g, '</li>' );
19
+ },
20
+ };
21
+
22
+ const defaultMarkdownItOptions: Options = {
23
+ breaks: true,
24
+ };
25
+
26
+ export default class MarkdownToHTML {
27
+ markdownConverter: MarkdownIt;
28
+
29
+ constructor( options: Options = defaultMarkdownItOptions ) {
30
+ this.markdownConverter = new MarkdownIt( options );
31
+ }
32
+
33
+ /**
34
+ * Renders HTML from Markdown content with specified processing rules.
35
+ * @param {object} options - The options to use when rendering the HTML content
36
+ * @param {string} options.content - The Markdown content to render
37
+ * @param {string} options.rules - The rules to apply to the rendered content
38
+ * @returns {string} The rendered HTML content
39
+ */
40
+ render( { content, rules = 'all' }: { content: string; rules: Array< Fix > | 'all' } ): string {
41
+ const rendered = this.markdownConverter.render( content );
42
+ const rulesToApply = rules === 'all' ? Object.keys( fixes ) : rules;
43
+
44
+ return rulesToApply.reduce( ( renderedContent, rule ) => {
45
+ return fixes[ rule ]( renderedContent );
46
+ }, rendered );
47
+ }
48
+ }
package/src/types.ts CHANGED
@@ -93,6 +93,17 @@ export type { RecordingState } from './hooks/use-media-recording/index.js';
93
93
  */
94
94
  export type CancelablePromise< T = void > = Promise< T > & { canceled?: boolean };
95
95
 
96
+ export type Block = {
97
+ attributes?: {
98
+ [ key: string ]: unknown;
99
+ };
100
+ clientId?: string;
101
+ innerBlocks?: Block[];
102
+ isValid?: boolean;
103
+ name?: string;
104
+ originalContent?: string;
105
+ };
106
+
96
107
  /*
97
108
  * Transcription types
98
109
  */