]> git.gir.st - VimFx.git/blob - gulpfile.coffee
Fix lint errors
[VimFx.git] / gulpfile.coffee
1 ###
2 # Copyright Simon Lydell 2014.
3 #
4 # This file is part of VimFx.
5 #
6 # VimFx is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # VimFx is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with VimFx. If not, see <http://www.gnu.org/licenses/>.
18 ###
19
20 fs = require('fs')
21 path = require('path')
22 regexEscape = require('escape-string-regexp')
23 gulp = require('gulp')
24 coffee = require('gulp-coffee')
25 coffeelint = require('gulp-coffeelint')
26 git = require('gulp-git')
27 header = require('gulp-header')
28 mustache = require('gulp-mustache')
29 zip = require('gulp-zip')
30 marked = require('marked')
31 merge = require('merge2')
32 precompute = require('require-precompute')
33 request = require('request')
34 rimraf = require('rimraf')
35 runSequence = require('run-sequence')
36 pkg = require('./package.json')
37
38 DEST = 'build'
39 XPI = 'VimFx.xpi'
40 LOCALE = 'extension/locale'
41 TEST = 'extension/test'
42
43 test = '--test' in process.argv or '-t' in process.argv
44 ifTest = (value) -> if test then [value] else []
45
46 { join } = path
47 read = (filepath) -> fs.readFileSync(filepath).toString()
48 template = (data) -> mustache(data, {extension: ''})
49
50 gulp.task('default', ['push'])
51
52 gulp.task('clean', (callback) ->
53 rimraf(DEST, callback)
54 )
55
56 gulp.task('copy', ->
57 gulp.src(['extension/**/!(*.coffee|*.tmpl)', 'COPYING'])
58 .pipe(gulp.dest(DEST))
59 )
60
61 gulp.task('node_modules', ->
62 dependencies = (name for name of pkg.dependencies)
63 # Note! When installing or updating node modules, make sure that the following
64 # glob does not include too much or too little!
65 gulp.src("node_modules/+(#{ dependencies.join('|') })/\
66 {LICENSE,{,**/!(test)/}*.js}")
67 .pipe(gulp.dest("#{ DEST }/node_modules"))
68 )
69
70 gulp.task('coffee', ->
71 gulp.src([
72 'extension/bootstrap.coffee'
73 'extension/lib/**/*.coffee'
74 ifTest('extension/test/**/*.coffee')...
75 ], {base: 'extension'})
76 .pipe(coffee({bare: true}))
77 .pipe(gulp.dest(DEST))
78 )
79
80 gulp.task('chrome.manifest', ->
81 gulp.src('extension/chrome.manifest.tmpl')
82 .pipe(template({locales: fs.readdirSync(LOCALE).map((locale) -> {locale})}))
83 .pipe(gulp.dest(DEST))
84 )
85
86 gulp.task('install.rdf', ->
87 [ [ { name: creator } ], developers, contributors, translators ] =
88 read('PEOPLE.md').trim().replace(/^#.+\n|^\s*-\s*/mg, '').split('\n\n')
89 .map((block) -> block.split('\n').map((name) -> {name}))
90
91 getDescription = (locale) -> read(join(LOCALE, locale, 'description')).trim()
92
93 descriptions = fs.readdirSync(LOCALE)
94 .map((locale) -> {
95 locale: locale
96 description: getDescription(locale)
97 })
98
99 gulp.src('extension/install.rdf.tmpl')
100 .pipe(template({
101 version: pkg.version
102 minVersion: pkg.firefoxVersions.min
103 maxVersion: pkg.firefoxVersions.max
104 creator, developers, contributors, translators
105 defaultDescription: getDescription('en-US')
106 descriptions
107 }))
108 .pipe(gulp.dest(DEST))
109 )
110
111 gulp.task('require-data', ['node_modules'], ->
112 data = JSON.stringify(precompute('.'), null, 2)
113 gulp.src('extension/require-data.js.tmpl')
114 .pipe(template({data}))
115 .pipe(gulp.dest(DEST))
116 )
117
118 gulp.task('tests-list', ->
119 list = JSON.stringify(fs.readdirSync(TEST)
120 .map((name) -> name.match(/^(test-.+)\.coffee$/)?[1])
121 .filter(Boolean)
122 )
123 gulp.src("#{ TEST }/tests-list.js.tmpl", {base: 'extension'})
124 .pipe(template({list}))
125 .pipe(gulp.dest(DEST))
126 )
127
128 gulp.task('templates', [
129 'chrome.manifest'
130 'install.rdf'
131 'require-data'
132 ifTest('tests-list')...
133 ])
134
135 gulp.task('build', (callback) ->
136 runSequence(
137 'clean',
138 ['copy', 'node_modules', 'coffee', 'templates'],
139 callback
140 )
141 )
142
143 gulp.task('xpi', ['build'], ->
144 gulp.src("#{ DEST }/**/*")
145 .pipe(zip(XPI, {compress: false}))
146 .pipe(gulp.dest(DEST))
147 )
148
149 gulp.task('push', ['xpi'], ->
150 body = fs.readFileSync(join(DEST, XPI))
151 request.post({url: 'http://localhost:8888', body })
152 )
153
154 gulp.task('lint', ->
155 gulp.src(['extension/**/*.coffee', 'gulpfile.coffee'])
156 .pipe(coffeelint())
157 .pipe(coffeelint.reporter())
158 )
159
160 gulp.task('release', (callback) ->
161 { version } = pkg
162 message = "VimFx v#{ version }"
163 today = new Date().toISOString()[...10]
164 merge([
165 gulp.src('package.json'),
166 gulp.src('CHANGELOG.md')
167 .pipe(header("### #{ version } (#{ today })\n\n"))
168 .pipe(gulp.dest('.'))
169 ])
170 .pipe(git.commit(message))
171 .on('end', ->
172 git.tag("v#{ version }", message, callback)
173 )
174 )
175
176 gulp.task('changelog', ->
177 num = 1
178 for arg in process.argv when /^-[1-9]$/.test(arg)
179 num = Number(arg[1])
180 entries = read('CHANGELOG.md').split(/^### .+/m)[1..num].join('')
181 process.stdout.write(marked(entries))
182 )
183
184 gulp.task('faster', ->
185 gulp.src('gulpfile.coffee')
186 .pipe(coffee({bare: true}))
187 .pipe(gulp.dest('.'))
188 )
189
190 gulp.task('sync-locales', ->
191 baseLocale = 'en-US'
192 for arg in process.argv when arg[...2] == '--'
193 baseLocale = arg[2..]
194 for file in fs.readdirSync(join(LOCALE, baseLocale))
195 templateString = switch path.extname(file)
196 when '.properties' then '%key=%value'
197 when '.dtd' then '<!ENTITY %key "%value">'
198 syncLocale(file, baseLocale, templateString) if templateString
199 )
200
201 syncLocale = (fileName, baseLocaleName, templateString) ->
202 regex = ///^ #{
203 regexEscape(templateString)
204 .replace(/%key/, '([^\\s=]+)')
205 .replace(/%value/, '(.+)')
206 } $///
207 basePath = join(LOCALE, baseLocaleName, fileName)
208 base = parseLocaleFile(read(basePath), regex)
209 oldBasePath = "#{basePath}.old"
210 if fs.existsSync(oldBasePath)
211 oldBase = parseLocaleFile(read(oldBasePath), regex)
212 for localeName in fs.readdirSync(LOCALE) when localeName != baseLocaleName
213 localePath = join(LOCALE, localeName, fileName)
214 locale = parseLocaleFile(read(localePath), regex)
215 newLocale = base.template.map((line) ->
216 if Array.isArray(line)
217 [ key ] = line
218 oldValue = oldBase?.keys[key]
219 value =
220 if (oldValue? and oldValue != base.keys[key]) or
221 key not of locale.keys
222 base.keys[key]
223 else
224 locale.keys[key]
225 return templateString.replace(/%key/, key).replace(/%value/, value)
226 else
227 return line
228 )
229 fs.writeFileSync(localePath, newLocale.join(base.newline))
230 return
231
232 parseLocaleFile = (fileContents, regex) ->
233 keys = {}
234 lines = []
235 [ newline ] = fileContents.match(/\r?\n/)
236 for line in fileContents.split(newline)
237 line = line.trim()
238 [ match, key, value ] = line.match(regex) ? []
239 if match
240 keys[key] = value
241 lines.push([key])
242 else
243 lines.push(line)
244 return {keys, template: lines, newline}
Imprint / Impressum