@@ -35,17 +35,24 @@ export interface ExcelTextWriteScope {
3535}
3636
3737/** Exact single-cell text insertion through the native paste pipeline. */
38- export async function writeExcelLiteralText (
38+ export function writeExcelLiteralText ( scope : ExcelTextWriteScope , text : string , signal ?: AbortSignal ) : Promise < void > {
39+ return writeExcelNativeText ( scope , text , signal , true ) ;
40+ }
41+
42+ /** Native numeric/formula parsing with the same cancellation and history ownership as literal text. */
43+ export async function writeExcelNativeText (
3944 scope : ExcelTextWriteScope ,
4045 text : string ,
4146 signal ?: AbortSignal ,
47+ literal = false ,
48+ verify ?: ( ) => boolean ,
4249) : Promise < void > {
4350 signal ?. throwIfAborted ( ) ;
4451 if ( typeof text !== 'string' || ! text . length || text . length > 8000 || / [ \t \r \n ] / . test ( text ) )
4552 throw new Error ( 'Invalid document tool parameters' ) ;
4653 if ( ! scope . isCurrent ( ) ) throw new Error ( 'Paste target has expired' ) ;
4754 assertExcelTextWritable ( scope . api , scope . model , scope . cell , scope . nativeRange , scope . readonly ) ;
48- const format = captureExcelCellFormat ( scope . cell ) ;
55+ const format = literal ? captureExcelCellFormat ( scope . cell ) : undefined ;
4956 let editOwned = true ;
5057 let completedOwnership : ( ( ) => boolean ) | undefined ;
5158 // Navigation invalidates insertion, but does not transfer ownership of our
@@ -71,62 +78,72 @@ export async function writeExcelLiteralText(
7178 const targetCurrent = ( ) => ownsGroup ( ) && scope . isCurrent ( ) ;
7279 let temporaryFormatAttempted = false ;
7380 let pendingOwnership : ( ( ) => boolean ) | undefined ;
74- await withExcelTextFormat (
75- {
76- originalFormat : format . originalFormat ,
77- isCurrent : targetCurrent ,
78- createPoint : ( ) => scope . history . Create_NewPoint ( ) ,
79- startTransaction : ( ) => scope . history . StartTransaction ( ) ,
80- endTransaction : ( ) => {
81- const owned = current ( ) ;
82- scope . history . EndTransaction ( ) ;
83- if ( owned ) captureCompletion ( ) ;
84- } ,
85- setFormat : ( value ) => {
86- if ( temporaryFormatAttempted ) {
87- current ( ) ;
88- const currentFormat = scope . cell . getNumFormat ( ) ?. sFormat ;
89- if ( ! scope . isDocumentCurrent ( ) || ( currentFormat !== '@' && currentFormat !== format . originalFormat ) ) {
90- editOwned = false ;
91- throw new Error ( 'Paste target has expired' ) ;
81+ const paste = async ( ) => {
82+ try {
83+ await pasteExcelText ( scope . api , scope . view , scope . clipboardFormat , text , {
84+ signal,
85+ isCurrent : targetCurrent ,
86+ endPaste : scope . endPaste ,
87+ onNativeCompletion : captureCompletion ,
88+ captureOwnership : ( ) => {
89+ const proof = captureExcelHistoryOwnership ( scope . history , ownsGroup ) ;
90+ pendingOwnership = proof ;
91+ return ( ) => {
92+ const owned = proof ( ) ;
93+ pendingOwnership = undefined ;
94+ return owned ;
95+ } ;
96+ } ,
97+ onOwnershipLost : ( ) => {
98+ editOwned = false ;
99+ } ,
100+ } ) ;
101+ } catch ( error ) {
102+ // Stop/timeout can settle before a native continuation checks its proof.
103+ if ( pendingOwnership && ! pendingOwnership ( ) ) editOwned = false ;
104+ throw error ;
105+ }
106+ } ;
107+ if ( format )
108+ await withExcelTextFormat (
109+ {
110+ originalFormat : format . originalFormat ,
111+ isCurrent : targetCurrent ,
112+ createPoint : ( ) => scope . history . Create_NewPoint ( ) ,
113+ startTransaction : ( ) => scope . history . StartTransaction ( ) ,
114+ endTransaction : ( ) => {
115+ const owned = current ( ) ;
116+ scope . history . EndTransaction ( ) ;
117+ if ( owned ) captureCompletion ( ) ;
118+ } ,
119+ setFormat : ( value ) => {
120+ if ( temporaryFormatAttempted ) {
121+ current ( ) ;
122+ const currentFormat = scope . cell . getNumFormat ( ) ?. sFormat ;
123+ if (
124+ ! scope . isDocumentCurrent ( ) ||
125+ ( currentFormat !== '@' && currentFormat !== format . originalFormat )
126+ ) {
127+ editOwned = false ;
128+ throw new Error ( 'Paste target has expired' ) ;
129+ }
130+ if ( currentFormat === format . originalFormat ) return ;
92131 }
93- if ( currentFormat === format . originalFormat ) return ;
94- }
95- temporaryFormatAttempted = true ;
96- format . setFormat ( value ) ;
97- if ( completedOwnership && editOwned ) captureCompletion ( ) ;
132+ temporaryFormatAttempted = true ;
133+ format . setFormat ( value ) ;
134+ if ( completedOwnership && editOwned ) captureCompletion ( ) ;
135+ } ,
98136 } ,
99- } ,
100- async ( ) => {
101- try {
102- await pasteExcelText ( scope . api , scope . view , scope . clipboardFormat , text , {
103- signal,
104- isCurrent : targetCurrent ,
105- endPaste : scope . endPaste ,
106- onNativeCompletion : captureCompletion ,
107- captureOwnership : ( ) => {
108- const proof = captureExcelHistoryOwnership ( scope . history , ownsGroup ) ;
109- pendingOwnership = proof ;
110- return ( ) => {
111- const owned = proof ( ) ;
112- pendingOwnership = undefined ;
113- return owned ;
114- } ;
115- } ,
116- onOwnershipLost : ( ) => {
117- editOwned = false ;
118- } ,
119- } ) ;
120- } catch ( error ) {
121- // Stop/timeout can settle before a native continuation checks its proof.
122- if ( pendingOwnership && ! pendingOwnership ( ) ) editOwned = false ;
123- throw error ;
124- }
125- } ,
126- ) ;
137+ paste ,
138+ ) ;
139+ else await paste ( ) ;
127140 signal ?. throwIfAborted ( ) ;
128141 if ( ! targetCurrent ( ) ) throw new Error ( 'Paste target has expired' ) ;
129- if ( scope . cell . getValue ( ) !== text || scope . cell . getNumFormat ( ) ?. sFormat !== format . originalFormat )
142+ if (
143+ ( format &&
144+ ( scope . cell . getValue ( ) !== text || scope . cell . getNumFormat ( ) ?. sFormat !== format . originalFormat ) ) ||
145+ ( verify && ! verify ( ) )
146+ )
130147 throw new Error ( 'The change could not be verified. Check the document and use Undo if needed.' ) ;
131148 } ,
132149 ( ) => scope . isDocumentCurrent ( ) ,
0 commit comments