locize-cli 11.0.0 → 11.1.0

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/CHANGELOG.md CHANGED
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
5
5
  Project versioning adheres to [Semantic Versioning](http://semver.org/).
6
6
  Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
7
7
 
8
+ ## [11.1.0](https://github.com/locize/locize-cli/compare/v11.1.0...v11.0.0) - 2025-12-11
9
+
10
+ - replace internal csv library to address security advisory #110
11
+
8
12
  ## [11.0.0](https://github.com/locize/locize-cli/compare/v10.4.0...v11.0.0) - 2025-12-10
9
13
 
10
14
  - log/error is shown if cdnType is not defined, because of changing default to 'standard' instead of 'pro'
@@ -1,6 +1,6 @@
1
1
  const flatten = require('flat')
2
2
  const i18next2po = require('gettext-converter/cjs/i18next2po')
3
- const csvjson = require('csvjson')
3
+ const csv = require('fast-csv')
4
4
  const xlsx = require('xlsx')
5
5
  const yaml = require('yaml')
6
6
  const js2asr = require('android-string-resource/cjs/js2asr')
@@ -81,34 +81,18 @@ const convertToDesiredFormat = (
81
81
  const js2CsvData = Object.keys(flatten(data)).reduce((mem, k) => {
82
82
  const value = data[k] || ''
83
83
  const line = {
84
- // https://en.wikipedia.org/wiki/Delimiter-separated_values
85
- key: k.replace(/"/g, '""'),
84
+ key: k,
86
85
  [opt.referenceLanguage]: refNs[k] || '',
87
- [lng]: value.replace(/"/g, '""')
86
+ [lng]: value
88
87
  }
89
- line.key = line.key.replace(/\n/g, '\\NeWlInE\\')
90
- line[opt.referenceLanguage] = line[opt.referenceLanguage].replace(
91
- /\n/g,
92
- '\\NeWlInE\\'
93
- )
94
- line[lng] = line[lng].replace(/\n/g, '\\NeWlInE\\')
95
88
  mem.push(line)
96
89
 
97
90
  return mem
98
91
  }, [])
99
- const options = {
100
- delimiter: ',',
101
- wrap: true,
102
- headers: 'relative'
103
- // objectDenote: '.',
104
- // arrayDenote: '[]'
105
- }
106
- cb(
107
- null,
108
- `\ufeff${csvjson
109
- .toCSV(js2CsvData, options)
110
- .replace(/\\NeWlInE\\/g, '\n')}`
111
- )
92
+
93
+ csv.writeToString(js2CsvData, { headers: true, quoteColumns: true })
94
+ .then((data) => cb(null, `\ufeff${data}`))
95
+ .catch(cb)
112
96
  })
113
97
  return
114
98
  }
@@ -1,5 +1,5 @@
1
1
  const po2i18next = require('gettext-converter/cjs/po2i18next')
2
- const csvjson = require('csvjson')
2
+ const csv = require('fast-csv')
3
3
  const xlsx = require('xlsx')
4
4
  const yaml = require('yaml')
5
5
  const asr2js = require('android-string-resource/cjs/asr2js')
@@ -60,50 +60,26 @@ const convertToFlatFormat = (opt, data, lng, cb) => {
60
60
  return
61
61
  }
62
62
  if (opt.format === 'csv') {
63
- const options = {
64
- delimiter: ',',
65
- quote: '"'
66
- }
67
-
68
63
  // CRLF => LF
69
- let text = data.toString().replace(/\r\n/g, '\n')
70
-
71
- // handle multiline stuff
72
- const lines = text.split('\n')
73
- const toHandle = []
74
- lines.forEach((l) => {
75
- const amountOfOccurrencies = l.split('"').length - 1
76
- if (amountOfOccurrencies % 2 === 1) toHandle.push(l)
77
- })
78
- while (toHandle.length > 1) {
79
- let firstToHandle = toHandle.shift()
80
- const secondToHandle = toHandle.shift()
81
- const indexOfFirst = lines.indexOf(firstToHandle)
82
- const indexOfSecond = lines.indexOf(secondToHandle)
83
- let handlingIndex = indexOfFirst
84
- while (handlingIndex < indexOfSecond) {
85
- firstToHandle += `\\NeWlInE\\${lines[handlingIndex + 1]}`
86
- handlingIndex++
87
- }
88
- lines[indexOfFirst] = firstToHandle
89
- lines.splice(indexOfFirst + 1, indexOfSecond - indexOfFirst)
90
- }
91
- text = lines.join('\n')
64
+ const text = data.toString().replace(/\r\n/g, '\n')
92
65
 
93
- // https://en.wikipedia.org/wiki/Delimiter-separated_values
94
- // temporary replace "" with \_\" so we can revert this 3 lines after
95
- const jsonData = csvjson.toObject(text.replace(/""/g, '\\_\\"'), options)
96
- data = jsonData.reduce((mem, entry) => {
97
- if (entry.key && typeof entry[opt.referenceLanguage] === 'string') {
98
- mem[
99
- entry.key.replace(/\\_\\"/g, '"').replace(/\\NeWlInE\\/g, '\n')
100
- ] = entry[opt.referenceLanguage]
101
- .replace(/\\_\\"/g, '"')
102
- .replace(/\\NeWlInE\\/g, '\n')
103
- }
104
- return mem
105
- }, {})
106
- cb(null, data)
66
+ const res = []
67
+ csv.parseString(text, { headers: true, ignoreEmpty: true })
68
+ .on('error', cb)
69
+ .on('data', (row) => res.push(row))
70
+ .on('end', () => {
71
+ try {
72
+ data = res.reduce((mem, entry) => {
73
+ if (entry.key && typeof entry[opt.referenceLanguage] === 'string') {
74
+ mem[entry.key] = entry[opt.referenceLanguage]
75
+ }
76
+ return mem
77
+ }, {})
78
+ cb(null, data)
79
+ } catch (err) {
80
+ cb(err)
81
+ }
82
+ })
107
83
  return
108
84
  }
109
85
  if (opt.format === 'xlsx') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "locize-cli",
3
- "version": "11.0.0",
3
+ "version": "11.1.0",
4
4
  "description": "locize cli to import locales",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -13,9 +13,9 @@
13
13
  "cacheable-lookup": "6.1.0",
14
14
  "colors": "1.4.0",
15
15
  "commander": "9.5.0",
16
- "csvjson": "5.1.0",
17
16
  "diff": "7.0.0",
18
17
  "dotenv": "16.5.0",
18
+ "fast-csv": "5.0.5",
19
19
  "flat": "5.0.2",
20
20
  "fluent_conv": "3.3.0",
21
21
  "gettext-converter": "1.3.0",
@@ -38,8 +38,8 @@
38
38
  "@yao-pkg/pkg": "6.4.0",
39
39
  "eslint": "9.39.1",
40
40
  "eslint-plugin-import": "2.32.0",
41
- "neostandard": "0.12.2",
42
- "gh-release": "7.0.2"
41
+ "gh-release": "7.0.2",
42
+ "neostandard": "0.12.2"
43
43
  },
44
44
  "scripts": {
45
45
  "lint": "eslint .",