Skip to content

Commit e814d46

Browse files
j15zclaude
andcommitted
fix(chunkers): accept single-quoted FAQ items with trailing commas
session-policies.mdx and verified-domains.mdx write FAQ items with single-quoted multiline values and trailing commas; the double-quote-only item pattern matched nothing there, so the component consumer replaced those whole FAQ blocks with a space. Capture either quote style escape-aware (quotes of the other style inside a value are fine) and allow the trailing comma; captured values keep their quotes and are unquoted before unescaping. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 0a03670 commit e814d46

2 files changed

Lines changed: 38 additions & 5 deletions

File tree

apps/sim/lib/chunkers/docs-chunker.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,32 @@ describe('cleanContent FAQ extraction', () => {
7474
expect(cleaned).toContain('Yes, on enterprise plans.')
7575
})
7676

77+
it('extracts single-quoted multiline items with trailing commas (session-policies shape)', () => {
78+
const cleaned = cleanContent(
79+
[
80+
'<FAQ',
81+
' items={[',
82+
' {',
83+
" question: 'Do session policies apply to SSO sign-ins?',",
84+
' answer:',
85+
" 'Yes. Sessions created through SSO follow the same limits.',",
86+
' },',
87+
' {',
88+
' question: \'Does "Sign out all members" affect API keys?\',',
89+
" answer: 'No. API keys are unaffected.',",
90+
' },',
91+
' ]}',
92+
'/>',
93+
].join('\n')
94+
)
95+
96+
expect(cleaned).toContain('Do session policies apply to SSO sign-ins?')
97+
expect(cleaned).toContain('Yes. Sessions created through SSO follow the same limits.')
98+
expect(cleaned).toContain('Does "Sign out all members" affect API keys?')
99+
expect(cleaned).toContain('No. API keys are unaffected.')
100+
expect(cleaned).not.toContain('items=')
101+
})
102+
77103
it('unescapes escaped quotes in extracted strings', () => {
78104
const cleaned = cleanContent(
79105
'<FAQ items={[ { question: "What does \\"draft\\" mean?", answer: "An unsaved workflow." } ]} />'

apps/sim/lib/chunkers/docs-chunker.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,19 @@ interface Frontmatter {
2222
const logger = createLogger('DocsChunker')
2323

2424
/**
25-
* One `{ question: "...", answer: "..." }` FAQ item. Quoted strings are
26-
* consumed escape-aware, so braces or quotes inside an answer never end a
27-
* match early.
25+
* One `{ question: "...", answer: "..." }` FAQ item, in either quote style and
26+
* with an optional trailing comma (`session-policies.mdx` uses single-quoted
27+
* multiline items). Each captured value keeps its surrounding quotes — the
28+
* quoted strings are consumed escape-aware per style, so quotes of the other
29+
* style, braces, or escapes inside an answer never end a match early.
2830
*/
2931
const FAQ_ITEM_PATTERN =
30-
/\{\s*question:\s*"((?:[^"\\]|\\.)*)"\s*,\s*answer:\s*"((?:[^"\\]|\\.)*)"\s*\}/g
32+
/\{\s*question:\s*("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')\s*,\s*answer:\s*("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')\s*,?\s*\}/g
33+
34+
/** Strip a captured value's surrounding quotes (either style), then unescape. */
35+
function unquoteJsxString(value: string): string {
36+
return unescapeJsxString(value.slice(1, -1))
37+
}
3138

3239
function unescapeJsxString(value: string): string {
3340
return value.replace(/\\(.)/g, (_, char: string) =>
@@ -47,7 +54,7 @@ function unescapeJsxString(value: string): string {
4754
function extractFaqProse(items: string): string {
4855
const lines: string[] = []
4956
for (const match of items.matchAll(FAQ_ITEM_PATTERN)) {
50-
lines.push(unescapeJsxString(match[1]), unescapeJsxString(match[2]))
57+
lines.push(unquoteJsxString(match[1]), unquoteJsxString(match[2]))
5158
}
5259
if (lines.length === 0) return ' '
5360
return `\n${lines.join('\n').replace(/[<>{}]/g, '')}\n`

0 commit comments

Comments
 (0)