@@ -235,4 +235,186 @@ world: World`;
235235 const reparsed = await loader . pull ( "en" , result ) ;
236236 expect ( reparsed ) . toEqual ( data ) ;
237237 } ) ;
238+
239+ it ( "push should preserve mixed value quoting (some quoted, some unquoted)" , async ( ) => {
240+ const loader = createYamlLoader ( ) ;
241+ loader . setDefaultLocale ( "en" ) ;
242+
243+ // Mixed quoting: some values quoted, some plain, some YAML references
244+ const yamlInput = `gender:
245+ f: "Feminine"
246+ m: "Masculine"
247+ female: :@f
248+ male: :@m` ;
249+
250+ await loader . pull ( "en" , yamlInput ) ;
251+
252+ const data = {
253+ gender : {
254+ f : "Femenino" ,
255+ m : "Masculino" ,
256+ female : ":@f" ,
257+ male : ":@m" ,
258+ } ,
259+ } ;
260+
261+ const result = await loader . push ( "en" , data , yamlInput ) ;
262+
263+ // Quoted values should remain quoted
264+ expect ( result ) . toContain ( '"Femenino"' ) ;
265+ expect ( result ) . toContain ( '"Masculino"' ) ;
266+
267+ // YAML references should remain unquoted
268+ expect ( result ) . toContain ( "female: :@f" ) ;
269+ expect ( result ) . toContain ( "male: :@m" ) ;
270+
271+ // Should NOT quote all values globally
272+ expect ( result ) . not . toMatch ( / f e m a l e : \s * " : @ f " / ) ;
273+ expect ( result ) . not . toMatch ( / m a l e : \s * " : @ m " / ) ;
274+ } ) ;
275+
276+ it ( "push should preserve mixed key quoting (some keys quoted, some unquoted)" , async ( ) => {
277+ const loader = createYamlLoader ( ) ;
278+ loader . setDefaultLocale ( "en" ) ;
279+
280+ // Mixed key quoting: one key quoted, others plain
281+ const yamlInput = `gender:
282+ f: Feminine
283+ "m": Masculine
284+ n: Neutral` ;
285+
286+ await loader . pull ( "en" , yamlInput ) ;
287+
288+ const data = {
289+ gender : {
290+ f : "Femenino" ,
291+ m : "Masculino" ,
292+ n : "Neutro" ,
293+ } ,
294+ } ;
295+
296+ const result = await loader . push ( "en" , data , yamlInput ) ;
297+
298+ // Only 'm' key should be quoted
299+ expect ( result ) . toMatch ( / " m " : \s * M a s c u l i n o / ) ;
300+
301+ // Other keys should NOT be quoted
302+ expect ( result ) . toMatch ( / f : \s * F e m e n i n o / ) ;
303+ expect ( result ) . not . toContain ( '"f":' ) ;
304+ expect ( result ) . toMatch ( / n : \s * N e u t r o / ) ;
305+ expect ( result ) . not . toContain ( '"n":' ) ;
306+
307+ // Root key should not be quoted
308+ expect ( result ) . not . toContain ( '"gender":' ) ;
309+ } ) ;
310+
311+ it ( "push should preserve both mixed key and value quoting simultaneously" , async ( ) => {
312+ const loader = createYamlLoader ( ) ;
313+ loader . setDefaultLocale ( "en" ) ;
314+
315+ // Complex scenario: mixed keys AND mixed values
316+ const yamlInput = `config:
317+ "special-key": "quoted value"
318+ normalKey: plain value
319+ anotherKey: "another quoted"` ;
320+
321+ await loader . pull ( "en" , yamlInput ) ;
322+
323+ const data = {
324+ config : {
325+ "special-key" : "valor citado" ,
326+ normalKey : "valor plano" ,
327+ anotherKey : "otro citado" ,
328+ } ,
329+ } ;
330+
331+ const result = await loader . push ( "en" , data , yamlInput ) ;
332+
333+ // Quoted key should remain quoted
334+ expect ( result ) . toMatch ( / " s p e c i a l - k e y " : / ) ;
335+
336+ // Other keys should not be quoted
337+ expect ( result ) . toMatch ( / n o r m a l K e y : / ) ;
338+ expect ( result ) . not . toContain ( '"normalKey"' ) ;
339+ expect ( result ) . toMatch ( / a n o t h e r K e y : / ) ;
340+ expect ( result ) . not . toContain ( '"anotherKey"' ) ;
341+
342+ // Quoted values should remain quoted
343+ expect ( result ) . toContain ( '"valor citado"' ) ;
344+ expect ( result ) . toContain ( '"otro citado"' ) ;
345+
346+ // Plain value should remain plain
347+ expect ( result ) . toMatch ( / n o r m a l K e y : \s * v a l o r p l a n o / ) ;
348+ } ) ;
349+
350+ it ( "push should preserve nested mixed quoting" , async ( ) => {
351+ const loader = createYamlLoader ( ) ;
352+ loader . setDefaultLocale ( "en" ) ;
353+
354+ // Nested structure with mixed quoting at different levels
355+ const yamlInput = `i18n:
356+ inflections:
357+ gender:
358+ f: "Feminine"
359+ "m": "Masculine"
360+ female: :@f` ;
361+
362+ await loader . pull ( "en" , yamlInput ) ;
363+
364+ const data = {
365+ i18n : {
366+ inflections : {
367+ gender : {
368+ f : "Femenino" ,
369+ m : "Masculino" ,
370+ female : ":@f" ,
371+ } ,
372+ } ,
373+ } ,
374+ } ;
375+
376+ const result = await loader . push ( "en" , data , yamlInput ) ;
377+
378+ // Only 'm' key should be quoted
379+ expect ( result ) . toMatch ( / " m " : / ) ;
380+ expect ( result ) . not . toContain ( '"f":' ) ;
381+
382+ // Parent keys should not be quoted
383+ expect ( result ) . not . toContain ( '"i18n":' ) ;
384+ expect ( result ) . not . toContain ( '"inflections":' ) ;
385+ expect ( result ) . not . toContain ( '"gender":' ) ;
386+
387+ // Quoted value should be quoted, reference unquoted
388+ expect ( result ) . toContain ( '"Femenino"' ) ;
389+ expect ( result ) . toMatch ( / f e m a l e : \s * : @ f / ) ;
390+ } ) ;
391+
392+ it ( "push should preserve quoting in yaml-root-key format (locale as root)" , async ( ) => {
393+ const loader = createYamlLoader ( ) ;
394+ loader . setDefaultLocale ( "en" ) ;
395+
396+ const yamlInput = `en:
397+ "greeting": "Hello!"
398+ message: Welcome` ;
399+
400+ await loader . pull ( "en" , yamlInput ) ;
401+
402+ const data = {
403+ en : {
404+ greeting : "¡Hola!" ,
405+ message : "Bienvenido" ,
406+ } ,
407+ } ;
408+
409+ const result = await loader . push ( "en" , data , yamlInput ) ;
410+
411+ // The quoted key and value should remain quoted
412+ expect ( result ) . toContain ( '"greeting":' ) ;
413+ expect ( result ) . toContain ( '"¡Hola!"' ) ;
414+
415+ // The unquoted key and value should remain unquoted
416+ expect ( result ) . toMatch ( / \s m e s s a g e : \s / ) ; // message key unquoted
417+ expect ( result ) . not . toContain ( '"message"' ) ;
418+ expect ( result ) . toMatch ( / m e s s a g e : \s * B i e n v e n i d o / ) ; // value unquoted
419+ } ) ;
238420} ) ;
0 commit comments