diff --git a/data/onPostBuild/transpileMdxToMarkdown.test.ts b/data/onPostBuild/transpileMdxToMarkdown.test.ts index 86fcdd759b..fdfedc92a4 100644 --- a/data/onPostBuild/transpileMdxToMarkdown.test.ts +++ b/data/onPostBuild/transpileMdxToMarkdown.test.ts @@ -4,6 +4,7 @@ import { removeScriptTags, removeAnchorTags, removeJsxComments, + convertMethodSignatureToCode, convertImagePathsToGitHub, convertDocsLinksToMarkdown, convertJsxLinkProps, @@ -306,6 +307,50 @@ import Baz from 'qux'; }); }); + describe('convertMethodSignatureToCode', () => { + it('should convert simple MethodSignature to inline code', () => { + const input = 'rooms.get(name, options)'; + const output = convertMethodSignatureToCode(input); + expect(output).toBe('`rooms.get(name, options)`'); + }); + + it('should convert template literal MethodSignature to inline code', () => { + const input = '{`rooms.get(name, options)`}'; + const output = convertMethodSignatureToCode(input); + expect(output).toBe('`rooms.get(name, options)`'); + }); + + it('should handle MethodSignature with angle brackets in template literal', () => { + const input = '{`Map`}'; + const output = convertMethodSignatureToCode(input); + expect(output).toBe('`Map`'); + }); + + it('should handle multiple MethodSignatures', () => { + const input = `## Method A +methodA() + +## Method B +{\`methodB()\`}`; + const output = convertMethodSignatureToCode(input); + expect(output).toContain('`methodA()`'); + expect(output).toContain('`methodB()`'); + expect(output).not.toContain(''); + }); + + it('should preserve MethodSignature in code blocks', () => { + const input = '```jsx\npreserve this\n```'; + const output = convertMethodSignatureToCode(input); + expect(output).toContain('preserve this'); + }); + + it('should handle surrounding content', () => { + const input = 'Before\n\nmethod()\n\nAfter'; + const output = convertMethodSignatureToCode(input); + expect(output).toBe('Before\n\n`method()`\n\nAfter'); + }); + }); + describe('convertImagePathsToGitHub', () => { const githubBase = 'https://raw.githubusercontent.com/ably/docs/main/src'; diff --git a/data/onPostBuild/transpileMdxToMarkdown.ts b/data/onPostBuild/transpileMdxToMarkdown.ts index ffcacdc569..4c00e3c730 100644 --- a/data/onPostBuild/transpileMdxToMarkdown.ts +++ b/data/onPostBuild/transpileMdxToMarkdown.ts @@ -233,6 +233,22 @@ function removeJsxComments(content: string): string { return transformNonCodeBlocks(content, (text) => text.replace(/\{\/\*[\s\S]*?\*\/\}/g, '')); } +/** + * Convert MethodSignature components to inline code + * Handles both simple content and template literal syntax + * content → `content` + * {`content`} → `content` + */ +function convertMethodSignatureToCode(content: string): string { + return transformNonCodeBlocks(content, (text) => + text + // Template literal syntax: {`content`} + .replace(/\{`([^`]*)`\}<\/MethodSignature>/g, '`$1`') + // Simple syntax: content + .replace(/([^<{]+)<\/MethodSignature>/g, '`$1`'), + ); +} + /** * Convert image paths to GitHub raw URLs * Handles relative (../), absolute (/images/), and direct (images/) paths @@ -456,25 +472,28 @@ function transformMdxToMarkdown( // Stage 5: Remove JSX comments content = removeJsxComments(content); - // Stage 6: Strip hidden attribute from tables (makes them visible in markdown) + // Stage 6: Convert MethodSignature components to inline code + content = convertMethodSignatureToCode(content); + + // Stage 7: Strip hidden attribute from tables (makes them visible in markdown) content = stripHiddenFromTables(content); - // Stage 7: Convert image paths to GitHub URLs + // Stage 8: Convert image paths to GitHub URLs content = convertImagePathsToGitHub(content); - // Stage 8: Convert relative URLs to absolute URLs + // Stage 9: Convert relative URLs to absolute URLs content = convertRelativeUrls(content, siteUrl); - // Stage 9: Convert quoted /docs/ URLs to markdown links (for JSX props like link: '/docs/...') + // Stage 10: Convert quoted /docs/ URLs to markdown links (for JSX props like link: '/docs/...') content = convertJsxLinkProps(content, siteUrl); - // Stage 10: Convert /docs/ links to .md extension and remove ?lang= params + // Stage 11: Convert /docs/ links to .md extension and remove ?lang= params content = convertDocsLinksToMarkdown(content); - // Stage 11: Replace template variables + // Stage 12: Replace template variables content = replaceTemplateVariables(content); - // Stage 12: Prepend title as markdown heading + // Stage 13: Prepend title as markdown heading const finalContent = `# ${title}\n\n${intro ? `${intro}\n\n` : ''}${content}`; return { content: finalContent, title, intro }; @@ -592,6 +611,7 @@ export { removeScriptTags, removeAnchorTags, removeJsxComments, + convertMethodSignatureToCode, stripHiddenFromTables, convertImagePathsToGitHub, convertDocsLinksToMarkdown, diff --git a/src/components/Layout/MDXWrapper.tsx b/src/components/Layout/MDXWrapper.tsx index 492501d799..caf5c5468d 100644 --- a/src/components/Layout/MDXWrapper.tsx +++ b/src/components/Layout/MDXWrapper.tsx @@ -21,6 +21,7 @@ import { Table, NestedTableProvider } from './mdx/NestedTable'; import { Tiles } from './mdx/tiles'; import { PageHeader } from './mdx/PageHeader'; import Admonition from './mdx/Admonition'; +import { MethodSignature } from './mdx/MethodSignature'; import { Frontmatter, PageContextType } from './Layout'; import { ActivePage } from './utils/nav'; @@ -285,6 +286,7 @@ const MDXWrapper: React.FC = ({ children, pageContext, location th: Table.Head, td: Table.Cell, Tiles, + MethodSignature, }} > diff --git a/src/components/Layout/mdx/MethodSignature.tsx b/src/components/Layout/mdx/MethodSignature.tsx new file mode 100644 index 0000000000..e50cf13535 --- /dev/null +++ b/src/components/Layout/mdx/MethodSignature.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import cn from '@ably/ui/core/utils/cn'; + +interface MethodSignatureProps { + children: React.ReactNode; + className?: string; +} + +/** + * A component for displaying method signatures prominently in API reference docs. + * Uses orange styling consistent with NestedTable property names. + * Features an L-shaped connector line linking to the parent header. + * + * Note: Must be placed immediately after an h2/h3 heading with standard margins. + * The connector line positioning assumes this layout relationship. + * + * Usage in MDX: + * rooms.get(name, options) + * + * For signatures containing special characters like < > { }, use a template literal: + * {`rooms.get(name, options)`} + */ +export const MethodSignature: React.FC = ({ children, className }) => { + return ( +
+ {/* L-shaped connector line */} +
+ + {children} + +
+ ); +}; diff --git a/src/pages/docs/chat/api/chat-client.mdx b/src/pages/docs/chat/api/chat-client.mdx new file mode 100644 index 0000000000..5215da2740 --- /dev/null +++ b/src/pages/docs/chat/api/chat-client.mdx @@ -0,0 +1,137 @@ +--- +title: ChatClient +meta_description: "API reference for the ChatClient class in the Ably Chat JavaScript SDK." +meta_keywords: "Ably Chat SDK, JavaScript, ChatClient API, constructor, dispose, rooms, connection, clientId, realtime" +--- + +The `ChatClient` class is the main entry point for using the Ably Chat SDK. It provides access to chat rooms, connection management, and the underlying Ably Realtime client. + +## Properties + +The `ChatClient` interface has the following properties: + + + +| Property | Description | Type | +| --- | --- | --- | +| rooms | The rooms object, used to get or create chat room instances. | [Rooms](/docs/chat/api/javascript/rooms) | +| connection | The connection object, used to monitor the connection status with Ably. | [Connection](/docs/chat/api/javascript/connection) | +| clientId | The client ID configured on the underlying Ably Realtime client. Used to identify the current user. May be `undefined` until authenticated with a token. | String or Undefined | +| realtime | The underlying Ably Realtime client instance. | Ably.Realtime | +| clientOptions | The resolved configuration options with defaults applied. |
| + +
+ + + +| Property | Required | Description | Type | +| --- | --- | --- | --- | +| logLevel | Optional | The logging level to use. Default: `LogLevel.Error`. | | +| logHandler | Optional | A custom log handler function that receives log messages from the SDK. |
| + +
+ + + +| Value | Description | +| --- | --- | +| Trace | Log all messages. | +| Debug | Log debug, info, warn, and error messages. | +| Info | Log info, warn, and error messages. | +| Warn | Log warn and error messages. | +| Error | Log error messages only. | +| Silent | Disable logging. | + + + + + +| Parameter | Required | Description | Type | +| --- | --- | --- | --- | +| message | Required | The log message. | String | +| level | Required | The severity level of the log message. | | +| context | Optional | Additional contextual data associated with the log entry. |
| + +
+ + + +`LogContext` is a type alias for `Record`. It represents an object of key-value pairs that can be used to provide additional context to a log message. + + + +## Create a new chat client + +{`new ChatClient(realtime: Realtime, clientOptions?: ChatClientOptions)`} + +Create a new `ChatClient` instance by passing an Ably Realtime client and optional configuration options. + + +```javascript +import * as Ably from 'ably'; +import { ChatClient } from '@ably/chat'; + +const realtimeClient = new Ably.Realtime({ + key: 'your-api-key', + clientId: 'user-123' +}); + +const chatClient = new ChatClient(realtimeClient, clientOptions); +``` + + +### Parameters + +The `ChatClient()` constructor takes the following parameters: + + + +| Parameter | Required | Description | Type | +| --- | --- | --- | --- | +| realtime | Required | An instance of the Ably Realtime client, configured with your API key and a `clientId`. The `clientId` is required for all chat operations. | Ably.Realtime | +| clientOptions | Optional | Configuration options for the Chat client. |
| + +
+ +## Dispose of the chat client
+ +{`chatClient.dispose(): Promise`} + +Disposes of the ChatClient instance and releases all resources, including all chat rooms. After calling this method, the ChatClient instance is no longer usable. + + +```javascript +await chatClient.dispose(); +``` + + +### Returns + +`Promise` - A promise that resolves when the client has been disposed. + +## Example + + +```javascript +import * as Ably from 'ably'; +import { ChatClient, LogLevel } from '@ably/chat'; + +const realtimeClient = new Ably.Realtime({ + key: 'your-api-key', + clientId: 'user-123' +}); + +const chatClient = new ChatClient(realtimeClient, { + logLevel: LogLevel.Debug +}); + +// Access rooms +const room = await chatClient.rooms.get('my-room'); + +// Check connection status +console.log(chatClient.connection.status); + +// Get current user ID +console.log(chatClient.clientId); +``` +