]> git.gir.st - VimFx.git/blob - gulpfile.coffee
Improve node_modules glob
[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 gulp = require('gulp')
23 coffee = require('gulp-coffee')
24 coffeelint = require('gulp-coffeelint')
25 git = require('gulp-git')
26 header = require('gulp-header')
27 mustache = require('gulp-mustache')
28 zip = require('gulp-zip')
29 marked = require('marked')
30 merge = require('merge2')
31 precompute = require('require-precompute')
32 request = require('request')
33 rimraf = require('rimraf')
34 runSequence = require('run-sequence')
35 pkg = require('./package.json')
36
37 DEST = 'build'
38 XPI = 'VimFx.xpi'
39 LOCALE = 'extension/locale'
40 TEST = 'extension/test'
41
42 test = '--test' in process.argv or '-t' in process.argv
43 ifTest = (value) -> if test then [value] else []
44
45 { join } = path
46 read = (filepath) -> fs.readFileSync(filepath).toString()
47 template = (data) -> mustache(data, {extension: ''})
48
49 gulp.task('default', ['push'])
50
51 gulp.task('clean', (callback) ->
52 rimraf(DEST, callback)
53 )
54
55 gulp.task('copy', ->
56 gulp.src(['extension/**/!(*.coffee|*.tmpl)', 'COPYING'])
57 .pipe(gulp.dest(DEST))
58 )
59
60 gulp.task('node_modules', ->
61 dependencies = (name for name of pkg.dependencies)
62 # Note! When installing or updating node modules, make sure that the following
63 # glob does not include too much or too little!
64 gulp.src("node_modules/+(#{ dependencies.join('|') })/\
65 {LICENSE*,{,**/!(test|examples)/}!(*min|*test*|*bench*).js}")
66 .pipe(gulp.dest("#{ DEST }/node_modules"))
67 )
68
69 gulp.task('coffee', ->
70 gulp.src([
71 'extension/bootstrap.coffee'
72 'extension/lib/**/*.coffee'
73 ifTest('extension/test/**/*.coffee')...
74 ], {base: 'extension'})
75 .pipe(coffee({bare: true}))
76 .pipe(gulp.dest(DEST))
77 )
78
79 gulp.task('chrome.manifest', ->
80 gulp.src('extension/chrome.manifest.tmpl')
81 .pipe(template({locales: fs.readdirSync(LOCALE).map((locale) -> {locale})}))
82 .pipe(gulp.dest(DEST))
83 )
84
85 gulp.task('install.rdf', ->
86 [ [ { name: creator } ], developers, contributors, translators ] =
87 read('PEOPLE.md').trim().replace(/^#.+\n|^\s*-\s*/mg, '').split('\n\n')
88 .map((block) -> block.split('\n').map((name) -> {name}))
89
90 getDescription = (locale) -> read(join(LOCALE, locale, 'description')).trim()
91
92 descriptions = fs.readdirSync(LOCALE)
93 .map((locale) -> {
94 locale: locale
95 description: getDescription(locale)
96 })
97
98 gulp.src('extension/install.rdf.tmpl')
99 .pipe(template({
100 version: pkg.version
101 minVersion: pkg.firefoxVersions.min
102 maxVersion: pkg.firefoxVersions.max
103 creator, developers, contributors, translators
104 defaultDescription: getDescription('en-US')
105 descriptions
106 }))
107 .pipe(gulp.dest(DEST))
108 )
109
110 gulp.task('require-data', ['node_modules'], ->
111 data = JSON.stringify(precompute('.'), null, 2)
112 gulp.src('extension/require-data.js.tmpl')
113 .pipe(template({data}))
114 .pipe(gulp.dest(DEST))
115 )
116
117 gulp.task('tests-list', ->
118 list = JSON.stringify(fs.readdirSync(TEST)
119 .map((name) -> name.match(/^(test-.+)\.coffee$/)?[1])
120 .filter(Boolean)
121 )
122 gulp.src("#{ TEST }/tests-list.js.tmpl", {base: 'extension'})
123 .pipe(template({list}))
124 .pipe(gulp.dest(DEST))
125 )
126
127 gulp.task('templates', [
128 'chrome.manifest'
129 'install.rdf'
130 'require-data'
131 ifTest('tests-list')...
132 ])
133
134 gulp.task('build', (callback) ->
135 runSequence(
136 'clean',
137 ['copy', 'node_modules', 'coffee', 'templates'],
138 callback
139 )
140 )
141
142 gulp.task('xpi', ['build'], ->
143 gulp.src("#{ DEST }/**/*")
144 .pipe(zip(XPI, {compress: false}))
145 .pipe(gulp.dest(DEST))
146 )
147
148 gulp.task('push', ['xpi'], ->
149 body = fs.readFileSync(join(DEST, XPI))
150 request.post({url: 'http://localhost:8888', body })
151 )
152
153 gulp.task('lint', ->
154 gulp.src(['extension/**/*.coffee', 'gulpfile.coffee'])
155 .pipe(coffeelint())
156 .pipe(coffeelint.reporter())
157 )
158
159 gulp.task('release', (callback) ->
160 { version } = pkg
161 message = "VimFx v#{ version }"
162 today = new Date().toISOString()[...10]
163 merge([
164 gulp.src('package.json'),
165 gulp.src('CHANGELOG.md')
166 .pipe(header("### #{ version } (#{ today })\n\n"))
167 .pipe(gulp.dest('.'))
168 ])
169 .pipe(git.commit(message))
170 .on('end', ->
171 git.tag("v#{ version }", message, callback)
172 )
173 )
174
175 gulp.task('changelog', ->
176 num = 1
177 for arg in process.argv when /^-[1-9]$/.test(arg)
178 num = Number(arg[1])
179 entries = read('CHANGELOG.md').split(/^### .+/m)[1..num].join('')
180 process.stdout.write(marked(entries))
181 )
182
183 gulp.task('faster', ->
184 gulp.src('gulpfile.coffee')
185 .pipe(coffee({bare: true}))
186 .pipe(gulp.dest('.'))
187 )
188
189 gulp.task('sync-locales', ->
190 baseLocale = 'en-US'
191 for arg in process.argv when arg[...2] == '--'
192 baseLocale = arg[2..]
193 fs.readdirSync(join(LOCALE, baseLocale))
194 .filter((file) -> path.extname(file) == '.properties')
195 .map(syncLocale.bind(undefined, baseLocale))
196 )
197
198 syncLocale = (baseLocaleName, fileName) ->
199 basePath = join(LOCALE, baseLocaleName, fileName)
200 base = parseLocaleFile(read(basePath))
201 oldBasePath = "#{basePath}.old"
202 if fs.existsSync(oldBasePath)
203 oldBase = parseLocaleFile(read(oldBasePath))
204 for localeName in fs.readdirSync(LOCALE) when localeName != baseLocaleName
205 localePath = join(LOCALE, localeName, fileName)
206 locale = parseLocaleFile(read(localePath))
207 newLocale = base.template.map((line) ->
208 if Array.isArray(line)
209 [ key ] = line
210 oldValue = oldBase?.keys[key]
211 value =
212 if (oldValue? and oldValue != base.keys[key]) or
213 key not of locale.keys
214 base.keys[key]
215 else
216 locale.keys[key]
217 return "#{ key }=#{ value }"
218 else
219 return line
220 )
221 fs.writeFileSync(localePath, newLocale.join(base.newline))
222 return
223
224 parseLocaleFile = (fileContents) ->
225 keys = {}
226 lines = []
227 [ newline ] = fileContents.match(/\r?\n/)
228 for line in fileContents.split(newline)
229 line = line.trim()
230 [ match, key, value ] = line.match(///^ ([^=]+) = (.*) $///) ? []
231 if match
232 keys[key] = value
233 lines.push([key])
234 else
235 lines.push(line)
236 return {keys, template: lines, newline}
Imprint / Impressum