@tim-greller/xgettext-regex 0.6.0 → 0.8.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/README.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  Minimum viable xgettext .pot file generator. Uses a configurable regex to get translation keys.
4
4
 
5
+ ___________________
6
+ *Note: This repository was forked from [alanshaw/xgettext-regex](https://github.com/alanshaw/xgettext-regex), which is no longer maintained.*
7
+ *It provides the following additional features:*
8
+
9
+ **✨ Improved command line interface (CLI)**
10
+ - **Configurable regex via CLI:** made the regex (and regexTextCaptureIndex) configurable.
11
+
12
+ **✨ Better support for complex syntax & other languages**
13
+ - Added an **improved default regex** and documentation for it.
14
+ - **Multiline extraction support:** rewrote matching to work across newlines, added regex dotAll support.
15
+ - Added support for **Java text blocks** using """.
16
+ - Fix bug of missing location information if two strings found in same line.
17
+
18
+ **✨ Better .pot file diffs to use it in version management like GIT**
19
+ - Deterministic order of the keys by file path
20
+ - Switched to **relative paths** for location comments to prohibit commiting personal workspace directory paths.
21
+ ___________________
22
+
5
23
  ## Examples
6
24
 
7
25
  ```sh
package/index.js CHANGED
@@ -2,9 +2,7 @@ var fs = require('fs')
2
2
  var path = require('path')
3
3
  var Readable = require('stream').Readable
4
4
  var through = require('through2')
5
- var readdirp = require('readdirp')
6
5
  var once = require('once')
7
- var xtend = require('xtend')
8
6
 
9
7
  function createDuplexStream (filename, opts) {
10
8
  filename = filename || ''
@@ -133,11 +131,68 @@ function getText (filename, opts) {
133
131
  return fs.createReadStream(filename).pipe(createDuplexStream(filename, opts))
134
132
  }
135
133
 
136
- var READDIRP_OPTS = {
134
+ var DEFAULT_WALK_OPTS = {
137
135
  fileFilter: ['!.*', '!*.png', '!*.jpg', '!*.gif', '!*.zip', '!*.gz'],
138
136
  directoryFilter: ['!.*', '!node_modules', '!coverage']
139
137
  }
140
138
 
139
+ function createFilter (patterns) {
140
+ var compiled = patterns.map(function (pattern) {
141
+ var isExclude = pattern[0] === '!'
142
+ var glob = isExclude ? pattern.slice(1) : pattern
143
+ var re = new RegExp('^' + glob.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^/]*') + '$')
144
+ return { re: re, isExclude: isExclude }
145
+ })
146
+ return function (name) {
147
+ for (var i = 0; i < compiled.length; i++) {
148
+ if (compiled[i].re.test(name)) return !compiled[i].isExclude
149
+ }
150
+ return true // include by default when no pattern matches
151
+ }
152
+ }
153
+
154
+ function walkDirectorySorted (dir, fileFilter, dirFilter, onFile, cb) {
155
+ fs.readdir(dir, function (er, entries) {
156
+ if (er) return cb(er)
157
+ entries.sort(function (a, b) {
158
+ return a.localeCompare(b, undefined, {sensitivity: 'base'})
159
+ })
160
+
161
+ var index = 0
162
+
163
+ function nextEntry () {
164
+ if (index >= entries.length) return cb()
165
+
166
+ var name = entries[index++]
167
+ var fullPath = path.join(dir, name)
168
+
169
+ fs.stat(fullPath, function (er, stats) {
170
+ if (er) {
171
+ console.error('walkDirectorySorted stat error', fullPath, er)
172
+ return nextEntry()
173
+ }
174
+ if (stats.isFile()) {
175
+ if (fileFilter(name)) {
176
+ onFile(fullPath, nextEntry)
177
+ } else {
178
+ nextEntry()
179
+ }
180
+ } else if (stats.isDirectory()) {
181
+ if (dirFilter(name)) {
182
+ walkDirectorySorted(fullPath, fileFilter, dirFilter, onFile, nextEntry)
183
+ } else {
184
+ nextEntry()
185
+ }
186
+ } else {
187
+ nextEntry()
188
+ }
189
+ })
190
+ }
191
+
192
+ nextEntry()
193
+ })
194
+ }
195
+
141
196
  function createDuplexFileStream (opts) {
142
197
  opts = opts || {}
143
198
  opts.readdirp = opts.readdirp || {}
@@ -166,32 +221,19 @@ function createDuplexFileStream (opts) {
166
221
  cb()
167
222
  })
168
223
  } else if (stats.isDirectory()) {
169
- var total = 0
170
- var complete = 0
171
- var readdirpComplete = false
172
-
173
- readdirp(filename, xtend(READDIRP_OPTS, opts.readdirp))
174
- .on('data', function (entry) {
175
- total++
176
-
177
- getText(entry.fullPath, opts)
178
- .on('data', function (entry) {self.push(entry)})
179
- .on('error', function (er) {
180
- console.error('Directory getText error', entry.fullPath, er)
181
- cb(er)
182
- })
183
- .on('end', function () {
184
- complete++
185
- if (total == complete && readdirpComplete) cb()
186
- })
187
- })
188
- .on('error', function (er) {
189
- console.error('Directory error', filename, er)
190
- cb(er)
191
- })
192
- .on('end', function () {
193
- readdirpComplete = true
194
- })
224
+ var walkOpts = Object.assign({}, DEFAULT_WALK_OPTS, opts.readdirp)
225
+ var fileFilter = createFilter(walkOpts.fileFilter)
226
+ var dirFilter = createFilter(walkOpts.directoryFilter)
227
+
228
+ walkDirectorySorted(filename, fileFilter, dirFilter, function (filePath, done) {
229
+ getText(filePath, opts)
230
+ .on('data', function (entry) { self.push(entry) })
231
+ .on('error', function (er) {
232
+ console.error('Directory getText error', filePath, er)
233
+ cb(er)
234
+ })
235
+ .on('end', done)
236
+ }, cb)
195
237
  }
196
238
  })
197
239
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tim-greller/xgettext-regex",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Minimum viable xgettext .po file generator. Uses a configurable regex to get translation keys.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,11 +11,9 @@
11
11
  "dependencies": {
12
12
  "minimist": "^1.1.0",
13
13
  "once": "^1.3.1",
14
- "readdirp": "^3.1.3",
15
14
  "split": "^1.0.1",
16
15
  "stream-combiner": "^0.2.1",
17
- "through2": "^3.0.1",
18
- "xtend": "^4.0.0"
16
+ "through2": "^3.0.1"
19
17
  },
20
18
  "bin": {
21
19
  "xgettext-regex": "bin/xgettext-regex.js"
package/test/test.js CHANGED
@@ -164,4 +164,20 @@ test('Can create .pot from multiple files/directories', function (t) {
164
164
  t.end()
165
165
  }))
166
166
  })
167
- })
167
+ })
168
+
169
+ test('Emits directory entries in deterministic path order', function (t) {
170
+ t.plan(3)
171
+
172
+ xgettext.createReadStream(__dirname + '/fixtures')
173
+ .pipe(concat({encoding: 'string'}, function (pot) {
174
+ var indexJade = pot.indexOf('msgid "index.js"')
175
+ var indexPhp = pot.indexOf('msgid "php hypertext preprocessor"')
176
+ var jsApp = pot.indexOf('msgid "app.js"')
177
+
178
+ t.ok(indexJade > -1, 'index.jade translation exists')
179
+ t.ok(indexPhp > indexJade, 'index.php content appears after index.jade content')
180
+ t.ok(jsApp > indexPhp, 'js/app.js content appears after index.php content')
181
+ t.end()
182
+ }))
183
+ })