Move template interpolation out of grunt into standalone script.
This commit is contained in:
parent
11ab484acf
commit
c296b5b6cf
114
Gruntfile.coffee
114
Gruntfile.coffee
@ -5,68 +5,6 @@ JSZip = require 'jszip'
|
|||||||
module.exports = (grunt) ->
|
module.exports = (grunt) ->
|
||||||
grunt.util.linefeed = '\n'
|
grunt.util.linefeed = '\n'
|
||||||
|
|
||||||
json = (data) ->
|
|
||||||
"`#{JSON.stringify(data).replace(/`/g, '\\`')}`"
|
|
||||||
|
|
||||||
importCSS = (filenames...) ->
|
|
||||||
grunt.template.process(
|
|
||||||
filenames.map((name) -> grunt.file.read "src/css/#{name}.css").join(''),
|
|
||||||
{data: grunt.config 'pkg'}
|
|
||||||
).trim().replace(/\n+/g, '\n').split(/^/m).map(JSON.stringify).join(' +\n').replace(/`/g, '\\`')
|
|
||||||
|
|
||||||
importHTML = (filename) ->
|
|
||||||
html grunt.template.process(grunt.file.read("src/#{filename}.html").replace(/^ +/gm, '').replace(/\r?\n/g, ''), data: grunt.config('pkg'))
|
|
||||||
|
|
||||||
parseTemplate = (template, context='') ->
|
|
||||||
context0 = context
|
|
||||||
parts = []
|
|
||||||
text = template
|
|
||||||
while text
|
|
||||||
if part = text.match /^(?:[^{}\\]|\\.)+(?!{)/
|
|
||||||
text = text[part[0].length..]
|
|
||||||
unescaped = part[0].replace /\\(.)/g, '$1'
|
|
||||||
context = (context + unescaped)
|
|
||||||
.replace(/(=['"])[^'"<>]*/g, '$1')
|
|
||||||
.replace(/(<\w+)( [\w-]+((?=[ >])|=''|=""))*/g, '$1')
|
|
||||||
.replace(/^([^'"<>]+|<\/?\w+>)*/, '')
|
|
||||||
parts.push json unescaped
|
|
||||||
else if part = text.match /^([^}]){([^}`]*)}/
|
|
||||||
text = text[part[0].length..]
|
|
||||||
unless context is '' or (part[1] is '$' and /\=['"]$/.test context) or part[1] is '?'
|
|
||||||
throw new Error "Illegal insertion into HTML template (at #{context}): #{template}"
|
|
||||||
parts.push switch part[1]
|
|
||||||
when '$' then "E(`#{part[2]}`)"
|
|
||||||
when '&' then "`#{part[2]}`.innerHTML"
|
|
||||||
when '@' then "E.cat(`#{part[2]}`)"
|
|
||||||
when '?'
|
|
||||||
args = ['""', '""']
|
|
||||||
for i in [0...2]
|
|
||||||
break if text[0] isnt '{'
|
|
||||||
text = text[1..]
|
|
||||||
[args[i], text] = parseTemplate text, context
|
|
||||||
if text[0] isnt '}'
|
|
||||||
throw new Error "Unexpected characters in subtemplate (#{text}): #{template}"
|
|
||||||
text = text[1..]
|
|
||||||
"(if `#{part[2]}` then #{args[0]} else #{args[1]})"
|
|
||||||
else
|
|
||||||
throw new Error "Unrecognized substitution operator (#{part[1]}): #{template}"
|
|
||||||
else
|
|
||||||
break
|
|
||||||
if context isnt context0
|
|
||||||
throw new Error "HTML template is ill-formed (at #{context}): #{template}"
|
|
||||||
output = if parts.length is 0 then '""' else parts.join ' + '
|
|
||||||
[output, text]
|
|
||||||
|
|
||||||
html = (template) ->
|
|
||||||
[output, remaining] = parseTemplate template
|
|
||||||
if remaining
|
|
||||||
throw new Error "Unexpected characters in template (#{remaining}): #{template}"
|
|
||||||
"(innerHTML: #{output})"
|
|
||||||
|
|
||||||
assert = (statement, objs...) ->
|
|
||||||
return '' unless grunt.config('pkg').tests_enabled
|
|
||||||
"throw new Error 'Assertion failed: ' + #{json statement} unless #{statement}"
|
|
||||||
|
|
||||||
loadPkg = ->
|
loadPkg = ->
|
||||||
pkg = grunt.file.readJSON 'package.json'
|
pkg = grunt.file.readJSON 'package.json'
|
||||||
version = grunt.file.readJSON 'version.json'
|
version = grunt.file.readJSON 'version.json'
|
||||||
@ -78,17 +16,6 @@ module.exports = (grunt) ->
|
|||||||
pkg: loadPkg()
|
pkg: loadPkg()
|
||||||
|
|
||||||
concat:
|
concat:
|
||||||
options: process: Object.create(null, data:
|
|
||||||
get: ->
|
|
||||||
pkg = grunt.config 'pkg'
|
|
||||||
pkg.importCSS = importCSS
|
|
||||||
pkg.importHTML = importHTML
|
|
||||||
pkg.html = html
|
|
||||||
pkg.assert = assert
|
|
||||||
pkg.tests_enabled or= false
|
|
||||||
pkg
|
|
||||||
enumerable: true
|
|
||||||
)
|
|
||||||
coffee:
|
coffee:
|
||||||
src: [
|
src: [
|
||||||
'src/General/Config.coffee'
|
'src/General/Config.coffee'
|
||||||
@ -130,11 +57,9 @@ module.exports = (grunt) ->
|
|||||||
'src/General/Settings.coffee'
|
'src/General/Settings.coffee'
|
||||||
'src/General/Main.coffee'
|
'src/General/Main.coffee'
|
||||||
]
|
]
|
||||||
dest: 'tmp/script-<%= pkg.type %>.coffee'
|
dest: 'tmp/script.coffee'
|
||||||
crx:
|
crx:
|
||||||
files:
|
files:
|
||||||
'testbuilds/updates<%= pkg.meta.suffix[pkg.channel] %>.xml': 'src/meta/updates.xml'
|
|
||||||
'testbuilds/crx<%= pkg.meta.suffix[pkg.channel] %>/manifest.json': 'src/meta/manifest.json'
|
|
||||||
'testbuilds/crx<%= pkg.meta.suffix[pkg.channel] %>/script.js': [
|
'testbuilds/crx<%= pkg.meta.suffix[pkg.channel] %>/script.js': [
|
||||||
'src/meta/botproc.js'
|
'src/meta/botproc.js'
|
||||||
'LICENSE'
|
'LICENSE'
|
||||||
@ -144,10 +69,9 @@ module.exports = (grunt) ->
|
|||||||
'testbuilds/crx<%= pkg.meta.suffix[pkg.channel] %>/eventPage.js': 'tmp/eventPage-crx.js'
|
'testbuilds/crx<%= pkg.meta.suffix[pkg.channel] %>/eventPage.js': 'tmp/eventPage-crx.js'
|
||||||
userscript:
|
userscript:
|
||||||
files:
|
files:
|
||||||
'testbuilds/<%= pkg.name %><%= pkg.meta.suffix[pkg.channel] %>.meta.js': 'src/meta/metadata.js'
|
|
||||||
'testbuilds/<%= pkg.name %><%= pkg.meta.suffix[pkg.channel] %>.user.js': [
|
'testbuilds/<%= pkg.name %><%= pkg.meta.suffix[pkg.channel] %>.user.js': [
|
||||||
'src/meta/botproc.js'
|
'src/meta/botproc.js'
|
||||||
'src/meta/metadata.js'
|
'testbuilds/<%= pkg.name %><%= pkg.meta.suffix[pkg.channel] %>.meta.js'
|
||||||
'LICENSE'
|
'LICENSE'
|
||||||
'src/meta/usestrict.js'
|
'src/meta/usestrict.js'
|
||||||
'tmp/script-userscript.js'
|
'tmp/script-userscript.js'
|
||||||
@ -195,6 +119,17 @@ module.exports = (grunt) ->
|
|||||||
stdout: true
|
stdout: true
|
||||||
stderr: true
|
stderr: true
|
||||||
failOnError: true
|
failOnError: true
|
||||||
|
'templates-crx':
|
||||||
|
command: 'node_modules/.bin/coffee tools/templates.coffee tmp/script.coffee tmp/script-crx.coffee crx - <%= pkg.tests_enabled || "" %>'
|
||||||
|
'templates-crx-meta':
|
||||||
|
command: """
|
||||||
|
node_modules/.bin/coffee tools/templates.coffee src/meta/updates.xml testbuilds/updates<%= pkg.meta.suffix[pkg.channel] %>.xml crx <%= pkg.channel %>
|
||||||
|
node_modules/.bin/coffee tools/templates.coffee src/meta/manifest.json testbuilds/crx<%= pkg.meta.suffix[pkg.channel] %>/manifest.json crx <%= pkg.channel %>
|
||||||
|
""".split('\n').join('&&')
|
||||||
|
'templates-userscript':
|
||||||
|
command: 'node_modules/.bin/coffee tools/templates.coffee tmp/script.coffee tmp/script-userscript.coffee userscript - <%= pkg.tests_enabled || "" %>'
|
||||||
|
'templates-userscript-meta':
|
||||||
|
command: 'node_modules/.bin/coffee tools/templates.coffee src/meta/metadata.js testbuilds/<%= pkg.name %><%= pkg.meta.suffix[pkg.channel] %>.meta.js userscript <%= pkg.channel %>'
|
||||||
commit:
|
commit:
|
||||||
command: """
|
command: """
|
||||||
git commit -am "Release <%= pkg.meta.name %> v<%= pkg.meta.version %>."
|
git commit -am "Release <%= pkg.meta.name %> v<%= pkg.meta.version %>."
|
||||||
@ -374,10 +309,12 @@ module.exports = (grunt) ->
|
|||||||
|
|
||||||
grunt.registerTask 'build', [
|
grunt.registerTask 'build', [
|
||||||
'shell:npm'
|
'shell:npm'
|
||||||
|
'concat:coffee'
|
||||||
'concurrent:build'
|
'concurrent:build'
|
||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'build-crx-channel', [
|
grunt.registerTask 'build-crx-channel', [
|
||||||
|
'shell:templates-crx-meta'
|
||||||
'concat:crx'
|
'concat:crx'
|
||||||
'copy:crx'
|
'copy:crx'
|
||||||
'zip-crx'
|
'zip-crx'
|
||||||
@ -385,7 +322,7 @@ module.exports = (grunt) ->
|
|||||||
|
|
||||||
grunt.registerTask 'build-crx', [
|
grunt.registerTask 'build-crx', [
|
||||||
'set-build:crx'
|
'set-build:crx'
|
||||||
'concat:coffee'
|
'shell:templates-crx'
|
||||||
'coffee:script'
|
'coffee:script'
|
||||||
'coffee:eventPage'
|
'coffee:eventPage'
|
||||||
'jshint:script'
|
'jshint:script'
|
||||||
@ -427,27 +364,34 @@ module.exports = (grunt) ->
|
|||||||
'sign-channel:noupdate'
|
'sign-channel:noupdate'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
grunt.registerTask 'build-userscript-channel', [
|
||||||
|
'shell:templates-userscript-meta'
|
||||||
|
'concat:userscript'
|
||||||
|
]
|
||||||
|
|
||||||
grunt.registerTask 'build-userscript', [
|
grunt.registerTask 'build-userscript', [
|
||||||
'set-build:userscript'
|
'set-build:userscript'
|
||||||
'concat:coffee'
|
'shell:templates-userscript'
|
||||||
'coffee:script'
|
'coffee:script'
|
||||||
'jshint:script'
|
'jshint:script'
|
||||||
'set-channel:stable'
|
'set-channel:stable'
|
||||||
'concat:userscript'
|
'build-userscript-channel'
|
||||||
'set-channel:beta'
|
'set-channel:beta'
|
||||||
'concat:userscript'
|
'build-userscript-channel'
|
||||||
'set-channel:noupdate'
|
'set-channel:noupdate'
|
||||||
'concat:userscript'
|
'build-userscript-channel'
|
||||||
'set-channel:dev'
|
'set-channel:dev'
|
||||||
'concat:userscript'
|
'build-userscript-channel'
|
||||||
'clean:tmpuserscript'
|
'clean:tmpuserscript'
|
||||||
'copy:install'
|
'copy:install'
|
||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'build-tests', [
|
grunt.registerTask 'build-tests', [
|
||||||
|
'shell:npm'
|
||||||
'enable-tests'
|
'enable-tests'
|
||||||
'build-userscript'
|
'concat:coffee'
|
||||||
'build-crx'
|
'build-crx'
|
||||||
|
'build-userscript'
|
||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'full', [
|
grunt.registerTask 'full', [
|
||||||
|
|||||||
62
npm-shrinkwrap.json
generated
62
npm-shrinkwrap.json
generated
@ -3,6 +3,10 @@
|
|||||||
"npm-shrinkwrap-version": "200.5.1",
|
"npm-shrinkwrap-version": "200.5.1",
|
||||||
"node-version": "v4.3.1",
|
"node-version": "v4.3.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"coffee-script": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz"
|
||||||
|
},
|
||||||
"crx": {
|
"crx": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/crx/-/crx-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/crx/-/crx-3.0.3.tgz",
|
||||||
@ -193,6 +197,60 @@
|
|||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.5.0.tgz"
|
"resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.5.0.tgz"
|
||||||
},
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "7.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"inflight": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||||
|
},
|
||||||
|
"minimatch": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.0.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.3.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.3.0.tgz"
|
||||||
|
},
|
||||||
|
"concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-is-absolute": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"grunt": {
|
"grunt": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz",
|
||||||
@ -1911,6 +1969,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.9.0.tgz"
|
||||||
|
},
|
||||||
"npm-shrinkwrap": {
|
"npm-shrinkwrap": {
|
||||||
"version": "200.5.1",
|
"version": "200.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/npm-shrinkwrap/-/npm-shrinkwrap-200.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/npm-shrinkwrap/-/npm-shrinkwrap-200.5.1.tgz",
|
||||||
|
|||||||
@ -59,8 +59,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"coffee-script": "^1.10.0",
|
||||||
"crx": "^3.0.3",
|
"crx": "^3.0.3",
|
||||||
"font-awesome": "4.5.0",
|
"font-awesome": "4.5.0",
|
||||||
|
"glob": "^7.0.3",
|
||||||
"grunt": "^1.0.1",
|
"grunt": "^1.0.1",
|
||||||
"grunt-concurrent": "^2.3.0",
|
"grunt-concurrent": "^2.3.0",
|
||||||
"grunt-contrib-clean": "^1.0.0",
|
"grunt-contrib-clean": "^1.0.0",
|
||||||
@ -74,6 +76,7 @@
|
|||||||
"grunt-webstore-upload": "^0.8.10",
|
"grunt-webstore-upload": "^0.8.10",
|
||||||
"jszip": "^2.6.0",
|
"jszip": "^2.6.0",
|
||||||
"load-grunt-tasks": "^3.5.0",
|
"load-grunt-tasks": "^3.5.0",
|
||||||
|
"lodash": "^4.9.0",
|
||||||
"npm-shrinkwrap": "^200.5.1"
|
"npm-shrinkwrap": "^200.5.1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
97
tools/templates.coffee
Normal file
97
tools/templates.coffee
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
fs = require 'fs'
|
||||||
|
path = require 'path'
|
||||||
|
_ = require 'lodash'
|
||||||
|
glob = require 'glob'
|
||||||
|
|
||||||
|
# disable ES6 delimiters
|
||||||
|
_.templateSettings.interpolate = /<%=([\s\S]+?)%>/g
|
||||||
|
|
||||||
|
read = (filename) -> fs.readFileSync filename, 'utf8'
|
||||||
|
|
||||||
|
pkg = JSON.parse(read 'package.json')
|
||||||
|
_.assign pkg.meta, JSON.parse(read 'version.json')
|
||||||
|
|
||||||
|
json = (data) ->
|
||||||
|
"`#{JSON.stringify(data).replace(/`/g, '\\`')}`"
|
||||||
|
|
||||||
|
importCSS = (filenames...) ->
|
||||||
|
text = filenames.map((name) -> read "src/css/#{name}.css").join('')
|
||||||
|
text = _.template(text)(pkg)
|
||||||
|
text.trim().replace(/\n+/g, '\n').split(/^/m).map(JSON.stringify).join(' +\n').replace(/`/g, '\\`')
|
||||||
|
|
||||||
|
importHTML = (filename) ->
|
||||||
|
text = read("src/#{filename}.html").replace(/^ +/gm, '').replace(/\r?\n/g, '')
|
||||||
|
text = _.template(text)(pkg)
|
||||||
|
html text
|
||||||
|
|
||||||
|
parseTemplate = (template, context='') ->
|
||||||
|
context0 = context
|
||||||
|
parts = []
|
||||||
|
text = template
|
||||||
|
while text
|
||||||
|
if part = text.match /^(?:[^{}\\]|\\.)+(?!{)/
|
||||||
|
text = text[part[0].length..]
|
||||||
|
unescaped = part[0].replace /\\(.)/g, '$1'
|
||||||
|
context = (context + unescaped)
|
||||||
|
.replace(/(=['"])[^'"<>]*/g, '$1')
|
||||||
|
.replace(/(<\w+)( [\w-]+((?=[ >])|=''|=""))*/g, '$1')
|
||||||
|
.replace(/^([^'"<>]+|<\/?\w+>)*/, '')
|
||||||
|
parts.push json unescaped
|
||||||
|
else if part = text.match /^([^}]){([^}`]*)}/
|
||||||
|
text = text[part[0].length..]
|
||||||
|
unless context is '' or (part[1] is '$' and /\=['"]$/.test context) or part[1] is '?'
|
||||||
|
throw new Error "Illegal insertion into HTML template (at #{context}): #{template}"
|
||||||
|
parts.push switch part[1]
|
||||||
|
when '$' then "E(`#{part[2]}`)"
|
||||||
|
when '&' then "`#{part[2]}`.innerHTML"
|
||||||
|
when '@' then "E.cat(`#{part[2]}`)"
|
||||||
|
when '?'
|
||||||
|
args = ['""', '""']
|
||||||
|
for i in [0...2]
|
||||||
|
break if text[0] isnt '{'
|
||||||
|
text = text[1..]
|
||||||
|
[args[i], text] = parseTemplate text, context
|
||||||
|
if text[0] isnt '}'
|
||||||
|
throw new Error "Unexpected characters in subtemplate (#{text}): #{template}"
|
||||||
|
text = text[1..]
|
||||||
|
"(if `#{part[2]}` then #{args[0]} else #{args[1]})"
|
||||||
|
else
|
||||||
|
throw new Error "Unrecognized substitution operator (#{part[1]}): #{template}"
|
||||||
|
else
|
||||||
|
break
|
||||||
|
if context isnt context0
|
||||||
|
throw new Error "HTML template is ill-formed (at #{context}): #{template}"
|
||||||
|
output = if parts.length is 0 then '""' else parts.join ' + '
|
||||||
|
[output, text]
|
||||||
|
|
||||||
|
html = (template) ->
|
||||||
|
[output, remaining] = parseTemplate template
|
||||||
|
if remaining
|
||||||
|
throw new Error "Unexpected characters in template (#{remaining}): #{template}"
|
||||||
|
"(innerHTML: #{output})"
|
||||||
|
|
||||||
|
assert = (statement, objs...) ->
|
||||||
|
return '' unless pkg.tests_enabled
|
||||||
|
"throw new Error 'Assertion failed: ' + #{json statement} unless #{statement}"
|
||||||
|
|
||||||
|
_.assign pkg, {importCSS, importHTML, html, assert}
|
||||||
|
|
||||||
|
pkg.grunt = file:
|
||||||
|
read: (filename, options) ->
|
||||||
|
if options?.encoding is 'base64'
|
||||||
|
fs.readFileSync(filename).toString('base64')
|
||||||
|
else
|
||||||
|
read filename
|
||||||
|
readJSON: (filename) -> JSON.parse read filename
|
||||||
|
expand: glob.sync
|
||||||
|
|
||||||
|
pkg.type = process.argv[4]
|
||||||
|
pkg.channel = process.argv[5]
|
||||||
|
pkg.tests_enabled = !!process.argv[6]
|
||||||
|
|
||||||
|
dir = path.dirname process.argv[3]
|
||||||
|
fs.mkdirSync dir unless fs.existsSync dir
|
||||||
|
|
||||||
|
text = read process.argv[2]
|
||||||
|
text = _.template(text)(pkg)
|
||||||
|
fs.writeFileSync process.argv[3], text
|
||||||
Loading…
x
Reference in New Issue
Block a user