@webority/mobile-chat 0.111.0 → 0.112.3

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/README.md CHANGED
@@ -130,10 +130,11 @@ package's, so a product passes one label set to both; `composerHint` is not show
130
130
  `keyboardAware={false}` to both inside a container that already does, and `keyboardOffset` (the
131
131
  tab bar height) above a tab bar. The composer's return key adds a new line; only the send button
132
132
  sends.
133
- - **`ChatMarkdown`**: renders a reply from a small, safe subset of Markdown: paragraphs, bold,
134
- italics, inline code, bullet and numbered lists, simple tables (scrolling sideways), headings,
135
- code blocks and rules. A link shows only when its href has the form `scheme:kind/id` and
136
- `resolveLink(href)` returns something; pressing it calls `onLinkPress(target)`. A web address
133
+ - **`ChatMarkdown`**: renders a reply through mobile-ui's `Markdown`, the one Markdown renderer
134
+ the phone uses, so the reply draws the same subset of Markdown as every other surface: paragraphs,
135
+ bold, italics, inline code, bullet and numbered lists, simple tables (scrolling sideways),
136
+ headings, code blocks and rules. A link shows only when its href has the form `scheme:kind/id`
137
+ and `resolveLink(href)` returns something; pressing it calls `onLinkPress(target)`. A web address
137
138
  never opens, and shows its label as plain text.
138
139
  - **`ReplyRating`**: Helpful and Not helpful under a stored reply; Not helpful then offers an
139
140
  optional note (`noteMaxLength`, default 1000).
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMarkdown=ChatMarkdown;var _mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_markdownParse=require("../markdownParse.js"),_jsxRuntime=require("react/jsx-runtime");const MONO=_reactNative.Platform.select({ios:"Menlo",android:"monospace",default:"monospace"}),createStyles=e=>_reactNative.StyleSheet.create({root:{gap:e.space.sm},listRow:{flexDirection:"row",gap:e.space.xs},marker:{minWidth:18},listText:{flex:1},code:{backgroundColor:e.colors["bg-subtle"],borderRadius:e.radius.sm,padding:e.space.sm},codeText:{fontFamily:MONO,fontSize:e.text.sm.size},inlineCode:{fontFamily:MONO,backgroundColor:e.colors["bg-subtle"],color:e.colors["text-body"]},link:{color:e.colors.link,textDecorationLine:"underline"},strong:{fontWeight:e.weight.bold},em:{fontStyle:"italic"},rule:{height:_reactNative.StyleSheet.hairlineWidth,backgroundColor:e.colors.border},table:{borderWidth:_reactNative.StyleSheet.hairlineWidth,borderColor:e.colors.border},row:{flexDirection:"row"},headerRow:{backgroundColor:e.colors["bg-subtle"]},cell:{minWidth:96,maxWidth:220,padding:e.space.xs,borderRightWidth:_reactNative.StyleSheet.hairlineWidth,borderBottomWidth:_reactNative.StyleSheet.hairlineWidth,borderColor:e.colors.border}});function Inline({tokens:e,styles:t,resolveLink:r,onLinkPress:i}){return(0,_jsxRuntime.jsx)(_jsxRuntime.Fragment,{children:e.map(e=>{switch(e.type){case"text":return(0,_jsxRuntime.jsx)(_reactNative.Text,{children:e.text},e.key);case"code":return(0,_jsxRuntime.jsx)(_reactNative.Text,{style:t.inlineCode,children:e.text},e.key);case"strong":case"em":return(0,_jsxRuntime.jsx)(_reactNative.Text,{style:"strong"===e.type?t.strong:t.em,children:(0,_jsxRuntime.jsx)(Inline,{tokens:e.children,styles:t,resolveLink:r,onLinkPress:i})},e.key);default:{const s=i?(0,_markdownParse.linkTarget)(e.href,r):null,n=(0,_jsxRuntime.jsx)(Inline,{tokens:e.children,styles:t});return null!==s&&i?(0,_jsxRuntime.jsx)(_reactNative.Text,{accessibilityRole:"link",style:t.link,onPress:()=>i(s),children:n},e.key):(0,_jsxRuntime.jsx)(_reactNative.Text,{children:n},e.key)}}})})}function ChatMarkdown({text:e,resolveLink:t,onLinkPress:r,testID:i}){const s=(0,_mobileUi.useTheme)(),n=(0,_react.useMemo)(()=>createStyles(s),[s]),o=(0,_react.useMemo)(()=>(0,_markdownParse.parseBlocks)(e),[e]),inline=e=>(0,_jsxRuntime.jsx)(Inline,{tokens:(0,_markdownParse.parseInline)(e),styles:n,resolveLink:t,onLinkPress:r});return(0,_jsxRuntime.jsx)(_reactNative.View,{style:n.root,testID:i,children:o.map(e=>{switch(e.type){case"paragraph":return(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"body",children:inline(e.lines.join("\n"))},e.key);case"heading":return(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"body",weight:"bold",accessibilityRole:"header",children:inline(e.text)},e.key);case"list":return(0,_jsxRuntime.jsx)(_reactNative.View,{children:e.items.map((t,r)=>(0,_jsxRuntime.jsxs)(_reactNative.View,{style:n.listRow,children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"body",style:n.marker,children:e.ordered?`${e.start+r}.`:"•"}),(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"body",style:n.listText,children:inline(t)})]},r))},e.key);case"table":return(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{horizontal:!0,showsHorizontalScrollIndicator:!1,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:n.table,children:[e.header,...e.rows].map((t,r)=>(0,_jsxRuntime.jsx)(_reactNative.View,{style:[n.row,0===r&&n.headerRow],children:e.header.map((e,i)=>(0,_jsxRuntime.jsx)(_reactNative.View,{style:n.cell,children:(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",weight:0===r?"semibold":void 0,children:inline(t[i]??"")})},i))},r))})},e.key);case"code":return(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{horizontal:!0,style:n.code,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{selectable:!0,style:[n.codeText,{color:s.colors["text-body"]}],children:e.text})},e.key);default:return(0,_jsxRuntime.jsx)(_reactNative.View,{style:n.rule},e.key)}})})}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMarkdown=ChatMarkdown;var _mobileUi=require("@webority/mobile-ui"),_jsxRuntime=require("react/jsx-runtime");function ChatMarkdown({text:e,resolveLink:r,onLinkPress:t,testID:i}){return(0,_jsxRuntime.jsx)(_mobileUi.Markdown,{links:"app",headings:"text",resolveLink:r,onAppLinkPress:t,testID:i,children:e})}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMessage=void 0;var _mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_labels=require("../labels.js"),_markdownParse=require("../markdownParse.js"),_ActionCard=require("./ActionCard.js"),_ChatMarkdown=require("./ChatMarkdown.js"),_ReplyRating=require("./ReplyRating.js"),_jsxRuntime=require("react/jsx-runtime");const inlineText=e=>e.map(e=>"text"===e.type||"code"===e.type?e.text:inlineText(e.children)).join(""),spokenText=e=>(0,_markdownParse.parseBlocks)(e).map(e=>{switch(e.type){case"paragraph":return inlineText((0,_markdownParse.parseInline)(e.lines.join(" ")));case"heading":return inlineText((0,_markdownParse.parseInline)(e.text));case"list":return e.items.map(e=>inlineText((0,_markdownParse.parseInline)(e))).join(". ");case"table":return[e.header,...e.rows].map(e=>e.join(", ")).join(". ");case"code":return e.text;default:return""}}).filter(Boolean).join("\n");function ChatMessageView({turn:e,onRate:t,resolveLink:s,onLinkPress:i,confirmAction:n,onViewTicket:r,renderReply:a,labels:o,testID:l="chat-message"}){const m=(0,_labels.mergeLabels)(o),u=(0,_mobileUi.useTheme)(),c=e.streaming&&!e.answer,x=(0,_react.useMemo)(()=>e.streaming?e.answer:spokenText(e.answer),[e.streaming,e.answer]),_=(0,_react.useMemo)(()=>({you:m.you}),[m.you]);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:u.space.sm},testID:l,children:[""!==e.question&&(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"mine",text:e.question,labels:_,testID:`${l}-question`}),c?(0,_jsxRuntime.jsx)(_mobileUi.TypingIndicator,{label:m.thinking,testID:`${l}-thinking`}):null,""!==e.answer?(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"theirs",author:m.assistant,text:x,streaming:e.streaming,testID:`${l}-answer`,children:a?a(e,{streaming:e.streaming}):(0,_jsxRuntime.jsx)(_ChatMarkdown.ChatMarkdown,{text:e.answer,resolveLink:s,onLinkPress:i})}):null,e.error&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),n&&!e.streaming&&e.actions.map(e=>(0,_jsxRuntime.jsx)(_ActionCard.ActionCard,{action:e,confirmAction:n,onViewTicket:r,labels:o},e.token)),t&&e.messageId&&!e.streaming&&(0,_jsxRuntime.jsx)(_ReplyRating.ReplyRating,{rating:e.rating,onRate:(s,i)=>t(e.id,s,i),labels:o})]})}const ChatMessage=exports.ChatMessage=(0,_react.memo)(ChatMessageView);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMessage=void 0;var _markdownCore=require("@webority/markdown-core"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_labels=require("../labels.js"),_ActionCard=require("./ActionCard.js"),_ChatMarkdown=require("./ChatMarkdown.js"),_ReplyRating=require("./ReplyRating.js"),_jsxRuntime=require("react/jsx-runtime");function ChatMessageView({turn:e,onRate:t,resolveLink:i,onLinkPress:s,confirmAction:r,onViewTicket:a,renderReply:n,labels:o,testID:l="chat-message"}){const m=(0,_labels.mergeLabels)(o),u=(0,_mobileUi.useTheme)(),c=e.streaming&&!e.answer,_=(0,_react.useMemo)(()=>e.streaming?e.answer:(0,_markdownCore.markdownToPlainText)(e.answer),[e.streaming,e.answer]),g=(0,_react.useMemo)(()=>({you:m.you}),[m.you]);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:u.space.sm},testID:l,children:[""!==e.question&&(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"mine",text:e.question,labels:g,testID:`${l}-question`}),c?(0,_jsxRuntime.jsx)(_mobileUi.TypingIndicator,{label:m.thinking,testID:`${l}-thinking`}):null,""!==e.answer?(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"theirs",author:m.assistant,text:_,streaming:e.streaming,testID:`${l}-answer`,children:n?n(e,{streaming:e.streaming}):(0,_jsxRuntime.jsx)(_ChatMarkdown.ChatMarkdown,{text:e.answer,resolveLink:i,onLinkPress:s})}):null,e.error&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),r&&!e.streaming&&e.actions.map(e=>(0,_jsxRuntime.jsx)(_ActionCard.ActionCard,{action:e,confirmAction:r,onViewTicket:a,labels:o},e.token)),t&&e.messageId&&!e.streaming&&(0,_jsxRuntime.jsx)(_ReplyRating.ReplyRating,{rating:e.rating,onRate:(i,s)=>t(e.id,i,s),labels:o})]})}const ChatMessage=exports.ChatMessage=(0,_react.memo)(ChatMessageView);
@@ -1 +1 @@
1
- "use strict";import{Text,useTheme}from"@webority/mobile-ui";import{useMemo}from"react";import{Platform,Text as RNText,ScrollView,StyleSheet,View}from"react-native";import{linkTarget,parseBlocks,parseInline}from"../markdownParse.js";import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";const MONO=Platform.select({ios:"Menlo",android:"monospace",default:"monospace"}),createStyles=e=>StyleSheet.create({root:{gap:e.space.sm},listRow:{flexDirection:"row",gap:e.space.xs},marker:{minWidth:18},listText:{flex:1},code:{backgroundColor:e.colors["bg-subtle"],borderRadius:e.radius.sm,padding:e.space.sm},codeText:{fontFamily:MONO,fontSize:e.text.sm.size},inlineCode:{fontFamily:MONO,backgroundColor:e.colors["bg-subtle"],color:e.colors["text-body"]},link:{color:e.colors.link,textDecorationLine:"underline"},strong:{fontWeight:e.weight.bold},em:{fontStyle:"italic"},rule:{height:StyleSheet.hairlineWidth,backgroundColor:e.colors.border},table:{borderWidth:StyleSheet.hairlineWidth,borderColor:e.colors.border},row:{flexDirection:"row"},headerRow:{backgroundColor:e.colors["bg-subtle"]},cell:{minWidth:96,maxWidth:220,padding:e.space.xs,borderRightWidth:StyleSheet.hairlineWidth,borderBottomWidth:StyleSheet.hairlineWidth,borderColor:e.colors.border}});function Inline({tokens:e,styles:t,resolveLink:r,onLinkPress:o}){return _jsx(_Fragment,{children:e.map(e=>{switch(e.type){case"text":return _jsx(RNText,{children:e.text},e.key);case"code":return _jsx(RNText,{style:t.inlineCode,children:e.text},e.key);case"strong":case"em":return _jsx(RNText,{style:"strong"===e.type?t.strong:t.em,children:_jsx(Inline,{tokens:e.children,styles:t,resolveLink:r,onLinkPress:o})},e.key);default:{const s=o?linkTarget(e.href,r):null,l=_jsx(Inline,{tokens:e.children,styles:t});return _jsx(RNText,null!==s&&o?{accessibilityRole:"link",style:t.link,onPress:()=>o(s),children:l}:{children:l},e.key)}}})})}export function ChatMarkdown({text:e,resolveLink:t,onLinkPress:r,testID:o}){const s=useTheme(),l=useMemo(()=>createStyles(s),[s]),i=useMemo(()=>parseBlocks(e),[e]),inline=e=>_jsx(Inline,{tokens:parseInline(e),styles:l,resolveLink:t,onLinkPress:r});return _jsx(View,{style:l.root,testID:o,children:i.map(e=>{switch(e.type){case"paragraph":return _jsx(Text,{variant:"body",children:inline(e.lines.join("\n"))},e.key);case"heading":return _jsx(Text,{variant:"body",weight:"bold",accessibilityRole:"header",children:inline(e.text)},e.key);case"list":return _jsx(View,{children:e.items.map((t,r)=>_jsxs(View,{style:l.listRow,children:[_jsx(Text,{variant:"body",style:l.marker,children:e.ordered?`${e.start+r}.`:"•"}),_jsx(Text,{variant:"body",style:l.listText,children:inline(t)})]},r))},e.key);case"table":return _jsx(ScrollView,{horizontal:!0,showsHorizontalScrollIndicator:!1,children:_jsx(View,{style:l.table,children:[e.header,...e.rows].map((t,r)=>_jsx(View,{style:[l.row,0===r&&l.headerRow],children:e.header.map((e,o)=>_jsx(View,{style:l.cell,children:_jsx(Text,{variant:"bodySmall",weight:0===r?"semibold":void 0,children:inline(t[o]??"")})},o))},r))})},e.key);case"code":return _jsx(ScrollView,{horizontal:!0,style:l.code,children:_jsx(RNText,{selectable:!0,style:[l.codeText,{color:s.colors["text-body"]}],children:e.text})},e.key);default:return _jsx(View,{style:l.rule},e.key)}})})}
1
+ "use strict";import{Markdown}from"@webority/mobile-ui";import{jsx as _jsx}from"react/jsx-runtime";export function ChatMarkdown({text:e,resolveLink:r,onLinkPress:t,testID:s}){return _jsx(Markdown,{links:"app",headings:"text",resolveLink:r,onAppLinkPress:t,testID:s,children:e})}
@@ -1 +1 @@
1
- "use strict";import{MessageBubble,Text,TypingIndicator,useTheme}from"@webority/mobile-ui";import{memo,useMemo}from"react";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{parseBlocks,parseInline}from"../markdownParse.js";import{ActionCard}from"./ActionCard.js";import{ChatMarkdown}from"./ChatMarkdown.js";import{ReplyRating}from"./ReplyRating.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const inlineText=e=>e.map(e=>"text"===e.type||"code"===e.type?e.text:inlineText(e.children)).join(""),spokenText=e=>parseBlocks(e).map(e=>{switch(e.type){case"paragraph":return inlineText(parseInline(e.lines.join(" ")));case"heading":return inlineText(parseInline(e.text));case"list":return e.items.map(e=>inlineText(parseInline(e))).join(". ");case"table":return[e.header,...e.rows].map(e=>e.join(", ")).join(". ");case"code":return e.text;default:return""}}).filter(Boolean).join("\n");function ChatMessageView({turn:e,onRate:s,resolveLink:t,onLinkPress:n,confirmAction:i,onViewTicket:r,renderReply:a,labels:o,testID:l="chat-message"}){const m=mergeLabels(o),c=useTheme(),p=e.streaming&&!e.answer,g=useMemo(()=>e.streaming?e.answer:spokenText(e.answer),[e.streaming,e.answer]),u=useMemo(()=>({you:m.you}),[m.you]);return _jsxs(View,{style:{gap:c.space.sm},testID:l,children:[""!==e.question&&_jsx(MessageBubble,{side:"mine",text:e.question,labels:u,testID:`${l}-question`}),p?_jsx(TypingIndicator,{label:m.thinking,testID:`${l}-thinking`}):null,""!==e.answer?_jsx(MessageBubble,{side:"theirs",author:m.assistant,text:g,streaming:e.streaming,testID:`${l}-answer`,children:a?a(e,{streaming:e.streaming}):_jsx(ChatMarkdown,{text:e.answer,resolveLink:t,onLinkPress:n})}):null,e.error&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),i&&!e.streaming&&e.actions.map(e=>_jsx(ActionCard,{action:e,confirmAction:i,onViewTicket:r,labels:o},e.token)),s&&e.messageId&&!e.streaming&&_jsx(ReplyRating,{rating:e.rating,onRate:(t,n)=>s(e.id,t,n),labels:o})]})}export const ChatMessage=memo(ChatMessageView);
1
+ "use strict";import{markdownToPlainText}from"@webority/markdown-core";import{MessageBubble,Text,TypingIndicator,useTheme}from"@webority/mobile-ui";import{memo,useMemo}from"react";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{ActionCard}from"./ActionCard.js";import{ChatMarkdown}from"./ChatMarkdown.js";import{ReplyRating}from"./ReplyRating.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";function ChatMessageView({turn:e,onRate:s,resolveLink:t,onLinkPress:r,confirmAction:i,onViewTicket:a,renderReply:n,labels:o,testID:m="chat-message"}){const l=mergeLabels(o),g=useTheme(),c=e.streaming&&!e.answer,u=useMemo(()=>e.streaming?e.answer:markdownToPlainText(e.answer),[e.streaming,e.answer]),d=useMemo(()=>({you:l.you}),[l.you]);return _jsxs(View,{style:{gap:g.space.sm},testID:m,children:[""!==e.question&&_jsx(MessageBubble,{side:"mine",text:e.question,labels:d,testID:`${m}-question`}),c?_jsx(TypingIndicator,{label:l.thinking,testID:`${m}-thinking`}):null,""!==e.answer?_jsx(MessageBubble,{side:"theirs",author:l.assistant,text:u,streaming:e.streaming,testID:`${m}-answer`,children:n?n(e,{streaming:e.streaming}):_jsx(ChatMarkdown,{text:e.answer,resolveLink:t,onLinkPress:r})}):null,e.error&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),i&&!e.streaming&&e.actions.map(e=>_jsx(ActionCard,{action:e,confirmAction:i,onViewTicket:a,labels:o},e.token)),s&&e.messageId&&!e.streaming&&_jsx(ReplyRating,{rating:e.rating,onRate:(t,r)=>s(e.id,t,r),labels:o})]})}export const ChatMessage=memo(ChatMessageView);
@@ -12,12 +12,6 @@ export interface ChatMarkdownProps<T = string> {
12
12
  onLinkPress?: (target: T) => void;
13
13
  testID?: string;
14
14
  }
15
- /**
16
- * Renders a reply from a small, safe subset of Markdown: paragraphs, bold, italics, inline code,
17
- * bullet and numbered lists, simple tables (scrolling sideways), headings (as bold lines), code
18
- * blocks and rules. It never opens a web address: a link shows only when its href has the form
19
- * `scheme:kind/id` and `resolveLink` maps it. Text still arriving updates the last block in place,
20
- * and an unclosed `**` shows as typed until its partner arrives.
21
- */
15
+ /** A reply never opens a web address, and its headings draw as bold lines, not large type. */
22
16
  export declare function ChatMarkdown<T = string>({ text, resolveLink, onLinkPress, testID }: ChatMarkdownProps<T>): React.ReactElement;
23
17
  //# sourceMappingURL=ChatMarkdown.d.ts.map
@@ -12,12 +12,6 @@ export interface ChatMarkdownProps<T = string> {
12
12
  onLinkPress?: (target: T) => void;
13
13
  testID?: string;
14
14
  }
15
- /**
16
- * Renders a reply from a small, safe subset of Markdown: paragraphs, bold, italics, inline code,
17
- * bullet and numbered lists, simple tables (scrolling sideways), headings (as bold lines), code
18
- * blocks and rules. It never opens a web address: a link shows only when its href has the form
19
- * `scheme:kind/id` and `resolveLink` maps it. Text still arriving updates the last block in place,
20
- * and an unclosed `**` shows as typed until its partner arrives.
21
- */
15
+ /** A reply never opens a web address, and its headings draw as bold lines, not large type. */
22
16
  export declare function ChatMarkdown<T = string>({ text, resolveLink, onLinkPress, testID }: ChatMarkdownProps<T>): React.ReactElement;
23
17
  //# sourceMappingURL=ChatMarkdown.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/mobile-chat",
3
- "version": "0.111.0",
3
+ "version": "0.112.3",
4
4
  "description": "AI assistant chat for Webority React Native apps: a streaming chat client, a store-agnostic chat hook, and the chat screen, thread, composer, past chats, reply rating and support action cards, built on @webority/mobile-ui.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -41,13 +41,16 @@
41
41
  "!**/*.spec.*",
42
42
  "!**/*.map"
43
43
  ],
44
+ "dependencies": {
45
+ "@webority/markdown-core": "0.112.3"
46
+ },
44
47
  "peerDependencies": {
45
48
  "react": "^19.1.0",
46
49
  "react-native": ">=0.81.0",
47
50
  "react-native-keyboard-controller": ">=1.21.9",
48
51
  "react-native-safe-area-context": ">=5.4.0",
49
- "@webority/mobile-core": "0.111.0",
50
- "@webority/mobile-ui": "0.111.0"
52
+ "@webority/mobile-ui": "0.112.3",
53
+ "@webority/mobile-core": "0.112.3"
51
54
  },
52
55
  "peerDependenciesMeta": {},
53
56
  "publishConfig": {
@@ -93,8 +96,8 @@
93
96
  "react-test-renderer": "19.2.8",
94
97
  "rimraf": "6.1.3",
95
98
  "typescript": "5.9.3",
96
- "@webority/mobile-core": "0.111.0",
97
- "@webority/mobile-ui": "0.111.0",
99
+ "@webority/mobile-core": "0.112.3",
100
+ "@webority/mobile-ui": "0.112.3",
98
101
  "@webority/mobile-dev": "0.0.0"
99
102
  },
100
103
  "scripts": {
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseInline=exports.parseBlocks=exports.linkTarget=void 0;const LINK_HREF=/^[a-z][a-z0-9+.-]*:[a-z0-9_-]+\/[a-z0-9_.~-]+$/i,FENCE=/^\s*```/,BULLET=/^\s*[-*+]\s+(.*)$/,ORDERED=/^\s*(\d{1,9})[.)]\s+(.*)$/,HEADING=/^\s{0,3}#{1,6}\s+(.*?)\s*#*\s*$/,RULE=/^\s*([-*_])(\s*\1){2,}\s*$/,TABLE_SEPARATOR=/^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?\s*$/,isTableRow=e=>e.includes("|"),tableCells=e=>{let t=e.trim();return t.startsWith("|")&&(t=t.slice(1)),t.endsWith("|")&&(t=t.slice(0,-1)),t.split("|").map(e=>e.trim())},startsTable=(e,t)=>isTableRow(e[t])&&t+1<e.length&&TABLE_SEPARATOR.test(e[t+1]),startsBlock=(e,t)=>{const s=e[t];return FENCE.test(s)||BULLET.test(s)||ORDERED.test(s)||HEADING.test(s)||RULE.test(s)||startsTable(e,t)},parseBlocks=e=>{const t=String(e??"").replace(/\r\n?/g,"\n").split("\n"),s=[];let n=0;for(;n<t.length;){const e=t[n];if(!e.trim()){n+=1;continue}if(FENCE.test(e)){const e=[];for(n+=1;n<t.length&&!FENCE.test(t[n]);)e.push(t[n]),n+=1;n+=1,s.push({type:"code",text:e.join("\n")});continue}if(startsTable(t,n)){const i=tableCells(e),r=[];for(n+=2;n<t.length&&t[n].trim()&&isTableRow(t[n]);)r.push(tableCells(t[n])),n+=1;s.push({type:"table",header:i,rows:r});continue}if(RULE.test(e)){s.push({type:"rule"}),n+=1;continue}const i=HEADING.exec(e);if(i){s.push({type:"heading",text:i[1]}),n+=1;continue}const r=ORDERED.exec(e);if(r||BULLET.test(e)){const e=Boolean(r),i=e?ORDERED:BULLET,l=[];for(;n<t.length&&t[n].trim();){const s=i.exec(t[n]);if(s)l.push(e?s[2]:s[1]);else{if(startsBlock(t,n))break;l[l.length-1]+=` ${t[n].trim()}`}n+=1}s.push({type:"list",ordered:e,start:r?Number(r[1]):1,items:l});continue}const l=[e];for(n+=1;n<t.length&&t[n].trim()&&!startsBlock(t,n);)l.push(t[n]),n+=1;s.push({type:"paragraph",lines:l})}return s.map((e,t)=>({...e,key:t}))};exports.parseBlocks=parseBlocks;const isWordChar=e=>Boolean(e)&&/[\p{L}\p{N}]/u.test(e??""),findClose=(e,t,s)=>{let n=e.indexOf(s,t);for(;-1!==n;){const i=e.slice(t,n),r=1===s.length&&(e[n+1]===s||e[n-1]===s),l="_"===s[0]&&isWordChar(e[n+s.length]);if(i.trim()&&!/^\s/.test(i)&&!/\s$/.test(i)&&!r&&!l)return n;n=e.indexOf(s,n+1)}return-1},parseInline=e=>{const t=[];let s="";const flush=()=>{s&&t.push({type:"text",text:s}),s=""};let n=0;for(;n<e.length;){const i=e[n];if("`"===i){const s=e.indexOf("`",n+1);if(s>n+1){flush(),t.push({type:"code",text:e.slice(n+1,s)}),n=s+1;continue}}if(("*"===i||"_"===i)&&e[n+1]===i){const r=i+i,l=findClose(e,n+2,r);if(-1!==l&&("_"!==i||!isWordChar(e[n-1]))){flush(),t.push({type:"strong",children:parseInline(e.slice(n+2,l))}),n=l+2;continue}s+=r,n+=2;continue}if("*"===i||"_"===i){const s=findClose(e,n+1,i);if(-1!==s&&("_"!==i||!isWordChar(e[n-1]))){flush(),t.push({type:"em",children:parseInline(e.slice(n+1,s))}),n=s+1;continue}}if("["===i){const s=/^\[([^\]\n]+)\]\(([^)\s]+)\)/.exec(e.slice(n));if(s){flush(),t.push({type:"link",href:s[2],children:parseInline(s[1])}),n+=s[0].length;continue}}s+=i,n+=1}return flush(),t.map((e,t)=>({...e,key:t}))};exports.parseInline=parseInline;const linkTarget=(e,t)=>t&&LINK_HREF.test(e)?t(e)??null:null;exports.linkTarget=linkTarget;
@@ -1 +0,0 @@
1
- "use strict";const LINK_HREF=/^[a-z][a-z0-9+.-]*:[a-z0-9_-]+\/[a-z0-9_.~-]+$/i,FENCE=/^\s*```/,BULLET=/^\s*[-*+]\s+(.*)$/,ORDERED=/^\s*(\d{1,9})[.)]\s+(.*)$/,HEADING=/^\s{0,3}#{1,6}\s+(.*?)\s*#*\s*$/,RULE=/^\s*([-*_])(\s*\1){2,}\s*$/,TABLE_SEPARATOR=/^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?\s*$/,isTableRow=t=>t.includes("|"),tableCells=t=>{let e=t.trim();return e.startsWith("|")&&(e=e.slice(1)),e.endsWith("|")&&(e=e.slice(0,-1)),e.split("|").map(t=>t.trim())},startsTable=(t,e)=>isTableRow(t[e])&&e+1<t.length&&TABLE_SEPARATOR.test(t[e+1]),startsBlock=(t,e)=>{const s=t[e];return FENCE.test(s)||BULLET.test(s)||ORDERED.test(s)||HEADING.test(s)||RULE.test(s)||startsTable(t,e)};export const parseBlocks=t=>{const e=String(t??"").replace(/\r\n?/g,"\n").split("\n"),s=[];let n=0;for(;n<e.length;){const t=e[n];if(!t.trim()){n+=1;continue}if(FENCE.test(t)){const t=[];for(n+=1;n<e.length&&!FENCE.test(e[n]);)t.push(e[n]),n+=1;n+=1,s.push({type:"code",text:t.join("\n")});continue}if(startsTable(e,n)){const i=tableCells(t),r=[];for(n+=2;n<e.length&&e[n].trim()&&isTableRow(e[n]);)r.push(tableCells(e[n])),n+=1;s.push({type:"table",header:i,rows:r});continue}if(RULE.test(t)){s.push({type:"rule"}),n+=1;continue}const i=HEADING.exec(t);if(i){s.push({type:"heading",text:i[1]}),n+=1;continue}const r=ORDERED.exec(t);if(r||BULLET.test(t)){const t=Boolean(r),i=t?ORDERED:BULLET,l=[];for(;n<e.length&&e[n].trim();){const s=i.exec(e[n]);if(s)l.push(t?s[2]:s[1]);else{if(startsBlock(e,n))break;l[l.length-1]+=` ${e[n].trim()}`}n+=1}s.push({type:"list",ordered:t,start:r?Number(r[1]):1,items:l});continue}const l=[t];for(n+=1;n<e.length&&e[n].trim()&&!startsBlock(e,n);)l.push(e[n]),n+=1;s.push({type:"paragraph",lines:l})}return s.map((t,e)=>({...t,key:e}))};const isWordChar=t=>Boolean(t)&&/[\p{L}\p{N}]/u.test(t??""),findClose=(t,e,s)=>{let n=t.indexOf(s,e);for(;-1!==n;){const i=t.slice(e,n),r=1===s.length&&(t[n+1]===s||t[n-1]===s),l="_"===s[0]&&isWordChar(t[n+s.length]);if(i.trim()&&!/^\s/.test(i)&&!/\s$/.test(i)&&!r&&!l)return n;n=t.indexOf(s,n+1)}return-1};export const parseInline=t=>{const e=[];let s="";const flush=()=>{s&&e.push({type:"text",text:s}),s=""};let n=0;for(;n<t.length;){const i=t[n];if("`"===i){const s=t.indexOf("`",n+1);if(s>n+1){flush(),e.push({type:"code",text:t.slice(n+1,s)}),n=s+1;continue}}if(("*"===i||"_"===i)&&t[n+1]===i){const r=i+i,l=findClose(t,n+2,r);if(-1!==l&&("_"!==i||!isWordChar(t[n-1]))){flush(),e.push({type:"strong",children:parseInline(t.slice(n+2,l))}),n=l+2;continue}s+=r,n+=2;continue}if("*"===i||"_"===i){const s=findClose(t,n+1,i);if(-1!==s&&("_"!==i||!isWordChar(t[n-1]))){flush(),e.push({type:"em",children:parseInline(t.slice(n+1,s))}),n=s+1;continue}}if("["===i){const s=/^\[([^\]\n]+)\]\(([^)\s]+)\)/.exec(t.slice(n));if(s){flush(),e.push({type:"link",href:s[2],children:parseInline(s[1])}),n+=s[0].length;continue}}s+=i,n+=1}return flush(),e.map((t,e)=>({...t,key:e}))};export const linkTarget=(t,e)=>e&&LINK_HREF.test(t)?e(t)??null:null;
@@ -1,59 +0,0 @@
1
- type BlockShape = {
2
- type: "paragraph";
3
- lines: string[];
4
- } | {
5
- type: "heading";
6
- text: string;
7
- } | {
8
- type: "list";
9
- ordered: boolean;
10
- start: number;
11
- items: string[];
12
- } | {
13
- type: "table";
14
- header: string[];
15
- rows: string[][];
16
- } | {
17
- type: "code";
18
- text: string;
19
- } | {
20
- type: "rule";
21
- };
22
- export type MarkdownBlock = BlockShape & {
23
- key: number;
24
- };
25
- type InlineShape = {
26
- type: "text";
27
- text: string;
28
- } | {
29
- type: "code";
30
- text: string;
31
- } | {
32
- type: "strong" | "em";
33
- children: InlineToken[];
34
- } | {
35
- type: "link";
36
- href: string;
37
- children: InlineToken[];
38
- };
39
- export type InlineToken = InlineShape & {
40
- key: number;
41
- };
42
- /**
43
- * Splits reply text into blocks: paragraphs, headings, bullet and numbered lists, simple tables,
44
- * code blocks and rules. Each block's `key` is its position, so text arriving at the end of a
45
- * streaming reply updates the last block in place and never remounts the ones before it.
46
- */
47
- export declare const parseBlocks: (text: string | null | undefined) => MarkdownBlock[];
48
- /**
49
- * Reads bold (`**` or `__`), italics (`*` or `_`), inline code and `[label](href)` links. A marker
50
- * with no partner yet (a reply still streaming) shows as the characters typed.
51
- */
52
- export declare const parseInline: (text: string) => InlineToken[];
53
- /**
54
- * What a reply link opens, or null when it may not open anything. Only `scheme:kind/id` hrefs
55
- * reach `resolveLink`; a web address never does, so a reply cannot send the person off the app.
56
- */
57
- export declare const linkTarget: <T>(href: string, resolveLink: ((href: string) => T | null | undefined) | undefined) => T | null;
58
- export {};
59
- //# sourceMappingURL=markdownParse.d.ts.map
@@ -1,59 +0,0 @@
1
- type BlockShape = {
2
- type: "paragraph";
3
- lines: string[];
4
- } | {
5
- type: "heading";
6
- text: string;
7
- } | {
8
- type: "list";
9
- ordered: boolean;
10
- start: number;
11
- items: string[];
12
- } | {
13
- type: "table";
14
- header: string[];
15
- rows: string[][];
16
- } | {
17
- type: "code";
18
- text: string;
19
- } | {
20
- type: "rule";
21
- };
22
- export type MarkdownBlock = BlockShape & {
23
- key: number;
24
- };
25
- type InlineShape = {
26
- type: "text";
27
- text: string;
28
- } | {
29
- type: "code";
30
- text: string;
31
- } | {
32
- type: "strong" | "em";
33
- children: InlineToken[];
34
- } | {
35
- type: "link";
36
- href: string;
37
- children: InlineToken[];
38
- };
39
- export type InlineToken = InlineShape & {
40
- key: number;
41
- };
42
- /**
43
- * Splits reply text into blocks: paragraphs, headings, bullet and numbered lists, simple tables,
44
- * code blocks and rules. Each block's `key` is its position, so text arriving at the end of a
45
- * streaming reply updates the last block in place and never remounts the ones before it.
46
- */
47
- export declare const parseBlocks: (text: string | null | undefined) => MarkdownBlock[];
48
- /**
49
- * Reads bold (`**` or `__`), italics (`*` or `_`), inline code and `[label](href)` links. A marker
50
- * with no partner yet (a reply still streaming) shows as the characters typed.
51
- */
52
- export declare const parseInline: (text: string) => InlineToken[];
53
- /**
54
- * What a reply link opens, or null when it may not open anything. Only `scheme:kind/id` hrefs
55
- * reach `resolveLink`; a web address never does, so a reply cannot send the person off the app.
56
- */
57
- export declare const linkTarget: <T>(href: string, resolveLink: ((href: string) => T | null | undefined) | undefined) => T | null;
58
- export {};
59
- //# sourceMappingURL=markdownParse.d.ts.map