@@ -11,66 +11,83 @@ export class ToTipTapVisitor extends BaserowFormulaVisitor {
1111
1212 visitRoot ( ctx ) {
1313 const result = ctx . expr ( ) . accept ( this )
14+ return this . mode === 'advanced'
15+ ? this . _wrapForAdvancedMode ( result )
16+ : this . _wrapForSimpleMode ( result )
17+ }
1418
15- // In advanced mode, ensure all content is wrapped in a single wrapper
16- if ( this . mode === 'advanced' ) {
17- const content = _ . isArray ( result ) ? result : [ result ]
18- const flatContent = content . flatMap ( ( item ) => {
19- // Filter out null or undefined items
20- if ( ! item ) return [ ]
21-
22- // If the item is an array (from functions without wrapper in advanced mode)
23- if ( Array . isArray ( item ) ) {
24- return item
25- }
26-
27- // If the item is a wrapper, extract its content
28- if ( item . type === 'wrapper' && item . content ) {
29- return item . content
30- }
19+ /**
20+ * Wraps content for advanced mode - flattens all content into a single wrapper
21+ */
22+ _wrapForAdvancedMode ( result ) {
23+ const content = _ . isArray ( result ) ? result : [ result ]
24+ const flatContent = this . _flattenContent ( content )
25+ this . _ensureStartsWithZWS ( flatContent )
26+
27+ return {
28+ type : 'doc' ,
29+ content : [
30+ {
31+ type : 'wrapper' ,
32+ content : flatContent ,
33+ } ,
34+ ] ,
35+ }
36+ }
3137
32- // Return the item if it has a type
33- return item . type ? [ item ] : [ ]
34- } )
38+ /**
39+ * Wraps content for simple mode - preserves wrapper structure or creates one
40+ */
41+ _wrapForSimpleMode ( result ) {
42+ if ( Array . isArray ( result ) ) {
43+ return this . _isArrayOfWrappers ( result )
44+ ? { type : 'doc' , content : result }
45+ : { type : 'doc' , content : [ { type : 'wrapper' , content : result } ] }
46+ }
3547
36- // Ensure content starts with ZWS
37- const firstNode = flatContent [ 0 ]
38- if (
39- ! firstNode ||
40- firstNode . type !== 'text' ||
41- firstNode . text !== '\u200B'
42- ) {
43- flatContent . unshift ( { type : 'text' , text : '\u200B' } )
44- }
48+ if ( result ?. type === 'wrapper' ) {
49+ return { type : 'doc' , content : [ result ] }
50+ }
4551
46- return {
47- type : 'doc' ,
48- content : [
49- {
50- type : 'wrapper' ,
51- content : flatContent ,
52- } ,
53- ] ,
54- }
52+ return {
53+ type : 'doc' ,
54+ content : [ { type : 'wrapper' , content : [ result ] } ] ,
5555 }
56+ }
5657
57- // In simple mode, wrap inline content in a wrapper
58- // The result can be a wrapper, an array of wrappers, or inline content
59- if ( Array . isArray ( result ) ) {
60- // Array of wrappers (e.g., from concat with newlines)
61- return { type : 'doc' , content : result }
62- } else if ( result ?. type === 'wrapper' ) {
63- // Already a wrapper
64- return { type : 'doc' , content : [ result ] }
65- } else {
66- // Inline content (text, nodes, etc.) - wrap it
67- return {
68- type : 'doc' ,
69- content : [ { type : 'wrapper' , content : [ result ] } ] ,
70- }
58+ /**
59+ * Flattens nested content, extracting items from wrappers and arrays
60+ */
61+ _flattenContent ( content ) {
62+ return content . flatMap ( ( item ) => {
63+ if ( ! item ) return [ ]
64+ if ( Array . isArray ( item ) ) return item
65+ if ( item . type === 'wrapper' && item . content ) return item . content
66+ return item . type ? [ item ] : [ ]
67+ } )
68+ }
69+
70+ /**
71+ * Ensures the content array starts with a Zero-Width Space text node
72+ */
73+ _ensureStartsWithZWS ( content ) {
74+ const firstNode = content [ 0 ]
75+ if (
76+ ! firstNode ||
77+ firstNode . type !== 'text' ||
78+ firstNode . text !== '\u200B'
79+ ) {
80+ content . unshift ( { type : 'text' , text : '\u200B' } )
7181 }
7282 }
7383
84+ /**
85+ * Checks if an array contains only wrapper nodes
86+ */
87+ _isArrayOfWrappers ( array ) {
88+ return array . every ( ( item ) => item ?. type === 'wrapper' )
89+ }
90+
7491 visitStringLiteral ( ctx ) {
7592 switch ( ctx . getText ( ) ) {
7693 case "'\n'" :
0 commit comments